|
@@ -1,265 +0,0 @@
|
1
|
|
-#ifndef ETHERBOOT_IO_H
|
2
|
|
-#define ETHERBOOT_IO_H
|
3
|
|
-
|
4
|
|
-#include <stdint.h>
|
5
|
|
-#include "virtaddr.h"
|
6
|
|
-
|
7
|
|
-/* virt_to_bus converts an addresss inside of etherboot [_start, _end]
|
8
|
|
- * into a memory access cards can use.
|
9
|
|
- */
|
10
|
|
-#define virt_to_bus virt_to_phys
|
11
|
|
-
|
12
|
|
-
|
13
|
|
-/* bus_to_virt reverses virt_to_bus, the address must be output
|
14
|
|
- * from virt_to_bus to be valid. This function does not work on
|
15
|
|
- * all bus addresses.
|
16
|
|
- */
|
17
|
|
-#define bus_to_virt phys_to_virt
|
18
|
|
-
|
19
|
|
-/* ioremap converts a random 32bit bus address into something
|
20
|
|
- * etherboot can access.
|
21
|
|
- */
|
22
|
|
-static inline void *ioremap(unsigned long bus_addr, unsigned long length __unused)
|
23
|
|
-{
|
24
|
|
- return bus_to_virt(bus_addr);
|
25
|
|
-}
|
26
|
|
-
|
27
|
|
-/* iounmap cleans up anything ioremap had to setup */
|
28
|
|
-static inline void iounmap(void *virt_addr __unused)
|
29
|
|
-{
|
30
|
|
- return;
|
31
|
|
-}
|
32
|
|
-
|
33
|
|
-/*
|
34
|
|
- * This file contains the definitions for the x86 IO instructions
|
35
|
|
- * inb/inw/inl/outb/outw/outl and the "string versions" of the same
|
36
|
|
- * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
|
37
|
|
- * versions of the single-IO instructions (inb_p/inw_p/..).
|
38
|
|
- *
|
39
|
|
- * This file is not meant to be obfuscating: it's just complicated
|
40
|
|
- * to (a) handle it all in a way that makes gcc able to optimize it
|
41
|
|
- * as well as possible and (b) trying to avoid writing the same thing
|
42
|
|
- * over and over again with slight variations and possibly making a
|
43
|
|
- * mistake somewhere.
|
44
|
|
- */
|
45
|
|
-
|
46
|
|
-/*
|
47
|
|
- * Thanks to James van Artsdalen for a better timing-fix than
|
48
|
|
- * the two short jumps: using outb's to a nonexistent port seems
|
49
|
|
- * to guarantee better timings even on fast machines.
|
50
|
|
- *
|
51
|
|
- * On the other hand, I'd like to be sure of a non-existent port:
|
52
|
|
- * I feel a bit unsafe about using 0x80 (should be safe, though)
|
53
|
|
- *
|
54
|
|
- * Linus
|
55
|
|
- */
|
56
|
|
-
|
57
|
|
-#ifdef SLOW_IO_BY_JUMPING
|
58
|
|
-#define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:")
|
59
|
|
-#else
|
60
|
|
-#define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80")
|
61
|
|
-#endif
|
62
|
|
-
|
63
|
|
-#ifdef REALLY_SLOW_IO
|
64
|
|
-#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
|
65
|
|
-#else
|
66
|
|
-#define SLOW_DOWN_IO __SLOW_DOWN_IO
|
67
|
|
-#endif
|
68
|
|
-
|
69
|
|
-/*
|
70
|
|
- * readX/writeX() are used to access memory mapped devices. On some
|
71
|
|
- * architectures the memory mapped IO stuff needs to be accessed
|
72
|
|
- * differently. On the x86 architecture, we just read/write the
|
73
|
|
- * memory location directly.
|
74
|
|
- */
|
75
|
|
-static inline __attribute__ (( always_inline )) unsigned long
|
76
|
|
-_readb ( volatile uint8_t *addr ) {
|
77
|
|
- unsigned long data = *addr;
|
78
|
|
- DBGIO ( "[%08lx] => %02lx\n", virt_to_phys ( addr ), data );
|
79
|
|
- return data;
|
80
|
|
-}
|
81
|
|
-static inline __attribute__ (( always_inline )) unsigned long
|
82
|
|
-_readw ( volatile uint16_t *addr ) {
|
83
|
|
- unsigned long data = *addr;
|
84
|
|
- DBGIO ( "[%08lx] => %04lx\n", virt_to_phys ( addr ), data );
|
85
|
|
- return data;
|
86
|
|
-}
|
87
|
|
-static inline __attribute__ (( always_inline )) unsigned long
|
88
|
|
-_readl ( volatile uint32_t *addr ) {
|
89
|
|
- unsigned long data = *addr;
|
90
|
|
- DBGIO ( "[%08lx] => %08lx\n", virt_to_phys ( addr ), data );
|
91
|
|
- return data;
|
92
|
|
-}
|
93
|
|
-#define readb( addr ) _readb ( ( volatile uint8_t * ) (addr) )
|
94
|
|
-#define readw( addr ) _readw ( ( volatile uint16_t * ) (addr) )
|
95
|
|
-#define readl( addr ) _readl ( ( volatile uint32_t * ) (addr) )
|
96
|
|
-
|
97
|
|
-static inline __attribute__ (( always_inline )) void
|
98
|
|
-_writeb ( unsigned long data, volatile uint8_t *addr ) {
|
99
|
|
- DBGIO ( "[%08lx] <= %02lx\n", virt_to_phys ( addr ), data );
|
100
|
|
- *addr = data;
|
101
|
|
-}
|
102
|
|
-static inline __attribute__ (( always_inline )) void
|
103
|
|
-_writew ( unsigned long data, volatile uint16_t *addr ) {
|
104
|
|
- DBGIO ( "[%08lx] <= %04lx\n", virt_to_phys ( addr ), data );
|
105
|
|
- *addr = data;
|
106
|
|
-}
|
107
|
|
-static inline __attribute__ (( always_inline )) void
|
108
|
|
-_writel ( unsigned long data, volatile uint32_t *addr ) {
|
109
|
|
- DBGIO ( "[%08lx] <= %08lx\n", virt_to_phys ( addr ), data );
|
110
|
|
- *addr = data;
|
111
|
|
-}
|
112
|
|
-#define writeb( b, addr ) _writeb ( (b), ( volatile uint8_t * ) (addr) )
|
113
|
|
-#define writew( b, addr ) _writew ( (b), ( volatile uint16_t * ) (addr) )
|
114
|
|
-#define writel( b, addr ) _writel ( (b), ( volatile uint32_t * ) (addr) )
|
115
|
|
-
|
116
|
|
-#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
|
117
|
|
-#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
|
118
|
|
-
|
119
|
|
-/*
|
120
|
|
- * Force strict CPU ordering.
|
121
|
|
- * And yes, this is required on UP too when we're talking
|
122
|
|
- * to devices.
|
123
|
|
- *
|
124
|
|
- * For now, "wmb()" doesn't actually do anything, as all
|
125
|
|
- * Intel CPU's follow what Intel calls a *Processor Order*,
|
126
|
|
- * in which all writes are seen in the program order even
|
127
|
|
- * outside the CPU.
|
128
|
|
- *
|
129
|
|
- * I expect future Intel CPU's to have a weaker ordering,
|
130
|
|
- * but I'd also expect them to finally get their act together
|
131
|
|
- * and add some real memory barriers if so.
|
132
|
|
- *
|
133
|
|
- * Some non intel clones support out of order store. wmb() ceases to be a
|
134
|
|
- * nop for these.
|
135
|
|
- */
|
136
|
|
-
|
137
|
|
-#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
|
138
|
|
-#define rmb() mb()
|
139
|
|
-#define wmb() mb();
|
140
|
|
-
|
141
|
|
-
|
142
|
|
-/*
|
143
|
|
- * Talk about misusing macros..
|
144
|
|
- */
|
145
|
|
-
|
146
|
|
-#define __OUT1(s,x) \
|
147
|
|
-extern void __out##s(unsigned x value, unsigned short port); \
|
148
|
|
-extern inline void __out##s(unsigned x value, unsigned short port) {
|
149
|
|
-
|
150
|
|
-#define __OUT2(s,s1,s2) \
|
151
|
|
-__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
|
152
|
|
-
|
153
|
|
-#define __OUT(s,s1,x) \
|
154
|
|
-__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); } \
|
155
|
|
-__OUT1(s##c,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); } \
|
156
|
|
-__OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); SLOW_DOWN_IO; } \
|
157
|
|
-__OUT1(s##c_p,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); SLOW_DOWN_IO; }
|
158
|
|
-
|
159
|
|
-#define __IN1(s,x) \
|
160
|
|
-extern unsigned x __in##s(unsigned short port); \
|
161
|
|
-extern inline unsigned x __in##s(unsigned short port) { unsigned x _v;
|
162
|
|
-
|
163
|
|
-#define __IN2(s,s1,s2) \
|
164
|
|
-__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
|
165
|
|
-
|
166
|
|
-#define __IN(s,s1,x,i...) \
|
167
|
|
-__IN1(s,x) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); return _v; } \
|
168
|
|
-__IN1(s##c,x) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); return _v; } \
|
169
|
|
-__IN1(s##_p,x) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); SLOW_DOWN_IO; return _v; } \
|
170
|
|
-__IN1(s##c_p,x) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); SLOW_DOWN_IO; return _v; }
|
171
|
|
-
|
172
|
|
-#define __INS(s) \
|
173
|
|
-extern void ins##s(unsigned short port, void * addr, unsigned long count); \
|
174
|
|
-extern inline void ins##s(unsigned short port, void * addr, unsigned long count) \
|
175
|
|
-{ __asm__ __volatile__ ("cld ; rep ; ins" #s \
|
176
|
|
-: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
|
177
|
|
-
|
178
|
|
-#define __OUTS(s) \
|
179
|
|
-extern void outs##s(unsigned short port, const void * addr, unsigned long count); \
|
180
|
|
-extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
|
181
|
|
-{ __asm__ __volatile__ ("cld ; rep ; outs" #s \
|
182
|
|
-: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
|
183
|
|
-
|
184
|
|
-__IN(b,"", char)
|
185
|
|
-__IN(w,"",short)
|
186
|
|
-__IN(l,"", long)
|
187
|
|
-
|
188
|
|
-__OUT(b,"b",char)
|
189
|
|
-__OUT(w,"w",short)
|
190
|
|
-__OUT(l,,int)
|
191
|
|
-
|
192
|
|
-__INS(b)
|
193
|
|
-__INS(w)
|
194
|
|
-__INS(l)
|
195
|
|
-
|
196
|
|
-__OUTS(b)
|
197
|
|
-__OUTS(w)
|
198
|
|
-__OUTS(l)
|
199
|
|
-
|
200
|
|
-/*
|
201
|
|
- * Note that due to the way __builtin_constant_p() works, you
|
202
|
|
- * - can't use it inside a inline function (it will never be true)
|
203
|
|
- * - you don't have to worry about side effects within the __builtin..
|
204
|
|
- */
|
205
|
|
-#define outb(val,port) \
|
206
|
|
-((__builtin_constant_p((port)) && (port) < 256) ? \
|
207
|
|
- __outbc((val),(port)) : \
|
208
|
|
- __outb((val),(port)))
|
209
|
|
-
|
210
|
|
-#define inb(port) \
|
211
|
|
-((__builtin_constant_p((port)) && (port) < 256) ? \
|
212
|
|
- __inbc(port) : \
|
213
|
|
- __inb(port))
|
214
|
|
-
|
215
|
|
-#define outb_p(val,port) \
|
216
|
|
-((__builtin_constant_p((port)) && (port) < 256) ? \
|
217
|
|
- __outbc_p((val),(port)) : \
|
218
|
|
- __outb_p((val),(port)))
|
219
|
|
-
|
220
|
|
-#define inb_p(port) \
|
221
|
|
-((__builtin_constant_p((port)) && (port) < 256) ? \
|
222
|
|
- __inbc_p(port) : \
|
223
|
|
- __inb_p(port))
|
224
|
|
-
|
225
|
|
-#define outw(val,port) \
|
226
|
|
-((__builtin_constant_p((port)) && (port) < 256) ? \
|
227
|
|
- __outwc((val),(port)) : \
|
228
|
|
- __outw((val),(port)))
|
229
|
|
-
|
230
|
|
-#define inw(port) \
|
231
|
|
-((__builtin_constant_p((port)) && (port) < 256) ? \
|
232
|
|
- __inwc(port) : \
|
233
|
|
- __inw(port))
|
234
|
|
-
|
235
|
|
-#define outw_p(val,port) \
|
236
|
|
-((__builtin_constant_p((port)) && (port) < 256) ? \
|
237
|
|
- __outwc_p((val),(port)) : \
|
238
|
|
- __outw_p((val),(port)))
|
239
|
|
-
|
240
|
|
-#define inw_p(port) \
|
241
|
|
-((__builtin_constant_p((port)) && (port) < 256) ? \
|
242
|
|
- __inwc_p(port) : \
|
243
|
|
- __inw_p(port))
|
244
|
|
-
|
245
|
|
-#define outl(val,port) \
|
246
|
|
-((__builtin_constant_p((port)) && (port) < 256) ? \
|
247
|
|
- __outlc((val),(port)) : \
|
248
|
|
- __outl((val),(port)))
|
249
|
|
-
|
250
|
|
-#define inl(port) \
|
251
|
|
-((__builtin_constant_p((port)) && (port) < 256) ? \
|
252
|
|
- __inlc(port) : \
|
253
|
|
- __inl(port))
|
254
|
|
-
|
255
|
|
-#define outl_p(val,port) \
|
256
|
|
-((__builtin_constant_p((port)) && (port) < 256) ? \
|
257
|
|
- __outlc_p((val),(port)) : \
|
258
|
|
- __outl_p((val),(port)))
|
259
|
|
-
|
260
|
|
-#define inl_p(port) \
|
261
|
|
-((__builtin_constant_p((port)) && (port) < 256) ? \
|
262
|
|
- __inlc_p(port) : \
|
263
|
|
- __inl_p(port))
|
264
|
|
-
|
265
|
|
-#endif /* ETHERBOOT_IO_H */
|