summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/include/arch/ppc/io.h
blob: 3449c5bf0155c2ea46932bd2ea26fcf90c344e2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#ifndef _ASM_IO_H
#define _ASM_IO_H

#include "asm/types.h"

#define NO_QEMU_PROTOS
#include "arch/common/fw_cfg.h"

extern char _start, _end;
extern unsigned long virt_offset;

#define phys_to_virt(phys) ((void *) ((unsigned long) (phys) - virt_offset))
#define virt_to_phys(virt) ((unsigned long) (virt) + virt_offset)

#ifndef BOOTSTRAP

extern unsigned long isa_io_base;

/*
 * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
 */
static inline uint8_t in_8(volatile uint8_t *addr)
{
	uint8_t ret;

	__asm__ __volatile__("lbz%U1%X1 %0,%1; eieio":"=r"(ret):"m"(*addr));
	return ret;
}

static inline void out_8(volatile uint8_t *addr, uint8_t val)
{
	__asm__ __volatile__("stb%U0%X0 %1,%0; eieio":"=m"(*addr):"r"(val));
}

static inline uint16_t in_le16(volatile uint16_t *addr)
{
	uint16_t ret;

	__asm__ __volatile__("lhbrx %0,0,%1; eieio":"=r"(ret):
			     "r"(addr), "m"(*addr));
	return ret;
}

static inline uint16_t in_be16(volatile uint16_t *addr)
{
	uint16_t ret;

	__asm__ __volatile__("lhz%U1%X1 %0,%1; eieio":"=r"(ret):"m"(*addr));
	return ret;
}

static inline void out_le16(volatile uint16_t *addr, uint16_t val)
{
	__asm__ __volatile__("sthbrx %1,0,%2; eieio":"=m"(*addr):"r"(val),
			     "r"(addr));
}

static inline void out_be16(volatile uint16_t *addr, uint16_t val)
{
	__asm__ __volatile__("sth%U0%X0 %1,%0; eieio":"=m"(*addr):"r"(val));
}

static inline uint32_t in_le32(volatile uint32_t *addr)
{
	uint32_t ret;

	__asm__ __volatile__("lwbrx %0,0,%1; eieio":"=r"(ret):
			     "r"(addr), "m"(*addr));
	return ret;
}

static inline uint32_t in_be32(volatile uint32_t *addr)
{
	uint32_t ret;

	__asm__ __volatile__("lwz%U1%X1 %0,%1; eieio":"=r"(ret):"m"(*addr));
	return ret;
}

static inline void out_le32(volatile uint32_t *addr, uint32_t val)
{
	__asm__ __volatile__("stwbrx %1,0,%2; eieio":"=m"(*addr):"r"(val),
			     "r"(addr));
}

static inline void out_be32(volatile unsigned *addr, uint32_t val)
{
	__asm__ __volatile__("stw%U0%X0 %1,%0; eieio":"=m"(*addr):"r"(val));
}

static inline void _insw_ns(volatile uint16_t * port, void *buf, int ns)
{
	uint16_t *b = (uint16_t *) buf;

	while (ns > 0) {
		*b++ = in_le16(port);
		ns--;
	}
}

static inline void _outsw_ns(volatile uint16_t * port, const void *buf,
			     int ns)
{
	uint16_t *b = (uint16_t *) buf;

	while (ns > 0) {
		out_le16(port, *b++);
		ns--;
	}
}

static inline void _insw(volatile uint16_t * port, void *buf, int ns)
{
	uint16_t *b = (uint16_t *) buf;

	while (ns > 0) {
		*b++ = in_be16(port);
		ns--;
	}
}

static inline void _outsw(volatile uint16_t * port, const void *buf,
			  int ns)
{
	uint16_t *b = (uint16_t *) buf;

	while (ns > 0) {
		out_be16(port, *b++);
		ns--;
	}
}


/*
 * The insw/outsw/insl/outsl functions don't do byte-swapping.
 * They are only used in practice for transferring buffers which
 * are arrays of bytes, and byte-swapping is not appropriate in
 * that case.  - paulus
 */

static inline void insw(uint16_t port, void *buf, int ns)
{
	_insw((uint16_t *)(port + isa_io_base), buf, ns);
}

static inline void outsw(uint16_t port, void *buf, int ns)
{
	_outsw((uint16_t *)(port + isa_io_base), buf, ns);
}


static inline uint8_t inb(uint16_t port)
{
	return in_8((uint8_t *)(port + isa_io_base));
}

static inline void outb(uint8_t val, uint16_t port)
{
	out_8((uint8_t *)(port + isa_io_base), val);
}

static inline uint16_t inw(uint16_t port)
{
	return in_le16((uint16_t *)(port + isa_io_base));
}

static inline void outw(uint16_t val, uint16_t port)
{
	out_le16((uint16_t *)(port + isa_io_base), val);
}

static inline uint32_t inl(uint16_t port)
{
	return in_le32((uint32_t *)(port + isa_io_base));
}

static inline void outl(uint32_t val, uint16_t port)
{
	out_le32((uint32_t *)(port + isa_io_base), val);
}

#else /* BOOTSTRAP */
#ifdef FCOMPILER
#define inb(reg) ((u8)0xff)
#define inw(reg) ((u16)0xffff)
#define inl(reg) ((u32)0xffffffff)
#define outb(reg, val) do{} while(0)
#define outw(reg, val) do{} while(0)
#define outl(reg, val) do{} while(0)
#else
extern u8 inb(u32 reg);
extern u16 inw(u32 reg);
extern u32 inl(u32 reg);
extern void insw(u32 reg, void *addr, unsigned long count);
extern void outb(u32 reg, u8 val);
extern void outw(u32 reg, u16 val);
extern void outl(u32 reg, u32 val);
extern void outsw(u32 reg, const void *addr, unsigned long count);
#endif
#endif

#if defined(CONFIG_QEMU)
#define FW_CFG_ARCH_WIDTH        (FW_CFG_ARCH_LOCAL + 0x00)
#define FW_CFG_ARCH_HEIGHT       (FW_CFG_ARCH_LOCAL + 0x01)
#define FW_CFG_ARCH_DEPTH        (FW_CFG_ARCH_LOCAL + 0x02)
#endif

#endif /* _ASM_IO_H */