]>
Commit | Line | Data |
---|---|---|
0f5d1d2a GK |
1 | /* |
2 | * Virtio Accessor Support: In case your target can change endian. | |
3 | * | |
4 | * Copyright IBM, Corp. 2013 | |
5 | * | |
6 | * Authors: | |
7 | * Rusty Russell <[email protected]> | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License as published by | |
11 | * the Free Software Foundation, either version 2 of the License, or | |
12 | * (at your option) any later version. | |
13 | * | |
14 | */ | |
2a6a4076 MA |
15 | |
16 | #ifndef QEMU_VIRTIO_ACCESS_H | |
17 | #define QEMU_VIRTIO_ACCESS_H | |
18 | ||
0f5d1d2a | 19 | #include "hw/virtio/virtio.h" |
8607f5c3 | 20 | #include "hw/virtio/virtio-bus.h" |
0f5d1d2a | 21 | |
c02d7030 GK |
22 | #if defined(TARGET_PPC64) || defined(TARGET_ARM) |
23 | #define LEGACY_VIRTIO_IS_BIENDIAN 1 | |
24 | #endif | |
25 | ||
0f5d1d2a GK |
26 | static inline bool virtio_access_is_big_endian(VirtIODevice *vdev) |
27 | { | |
c02d7030 | 28 | #if defined(LEGACY_VIRTIO_IS_BIENDIAN) |
e5157e31 GK |
29 | return virtio_is_big_endian(vdev); |
30 | #elif defined(TARGET_WORDS_BIGENDIAN) | |
95129d6f | 31 | if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) { |
3c185597 CH |
32 | /* Devices conforming to VIRTIO 1.0 or later are always LE. */ |
33 | return false; | |
34 | } | |
0f5d1d2a GK |
35 | return true; |
36 | #else | |
37 | return false; | |
38 | #endif | |
39 | } | |
40 | ||
41 | static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa) | |
42 | { | |
8607f5c3 JW |
43 | AddressSpace *dma_as = vdev->dma_as; |
44 | ||
0f5d1d2a | 45 | if (virtio_access_is_big_endian(vdev)) { |
8607f5c3 | 46 | return lduw_be_phys(dma_as, pa); |
0f5d1d2a | 47 | } |
8607f5c3 | 48 | return lduw_le_phys(dma_as, pa); |
0f5d1d2a GK |
49 | } |
50 | ||
51 | static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa) | |
52 | { | |
8607f5c3 JW |
53 | AddressSpace *dma_as = vdev->dma_as; |
54 | ||
0f5d1d2a | 55 | if (virtio_access_is_big_endian(vdev)) { |
8607f5c3 | 56 | return ldl_be_phys(dma_as, pa); |
0f5d1d2a | 57 | } |
8607f5c3 | 58 | return ldl_le_phys(dma_as, pa); |
0f5d1d2a GK |
59 | } |
60 | ||
61 | static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa) | |
62 | { | |
8607f5c3 JW |
63 | AddressSpace *dma_as = vdev->dma_as; |
64 | ||
0f5d1d2a | 65 | if (virtio_access_is_big_endian(vdev)) { |
8607f5c3 | 66 | return ldq_be_phys(dma_as, pa); |
0f5d1d2a | 67 | } |
8607f5c3 | 68 | return ldq_le_phys(dma_as, pa); |
0f5d1d2a GK |
69 | } |
70 | ||
71 | static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa, | |
72 | uint16_t value) | |
73 | { | |
8607f5c3 JW |
74 | AddressSpace *dma_as = vdev->dma_as; |
75 | ||
0f5d1d2a | 76 | if (virtio_access_is_big_endian(vdev)) { |
8607f5c3 | 77 | stw_be_phys(dma_as, pa, value); |
0f5d1d2a | 78 | } else { |
8607f5c3 | 79 | stw_le_phys(dma_as, pa, value); |
0f5d1d2a GK |
80 | } |
81 | } | |
82 | ||
83 | static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa, | |
84 | uint32_t value) | |
85 | { | |
8607f5c3 JW |
86 | AddressSpace *dma_as = vdev->dma_as; |
87 | ||
0f5d1d2a | 88 | if (virtio_access_is_big_endian(vdev)) { |
8607f5c3 | 89 | stl_be_phys(dma_as, pa, value); |
0f5d1d2a | 90 | } else { |
8607f5c3 | 91 | stl_le_phys(dma_as, pa, value); |
0f5d1d2a GK |
92 | } |
93 | } | |
94 | ||
95 | static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v) | |
96 | { | |
97 | if (virtio_access_is_big_endian(vdev)) { | |
98 | stw_be_p(ptr, v); | |
99 | } else { | |
100 | stw_le_p(ptr, v); | |
101 | } | |
102 | } | |
103 | ||
104 | static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v) | |
105 | { | |
106 | if (virtio_access_is_big_endian(vdev)) { | |
107 | stl_be_p(ptr, v); | |
108 | } else { | |
109 | stl_le_p(ptr, v); | |
110 | } | |
111 | } | |
112 | ||
113 | static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v) | |
114 | { | |
115 | if (virtio_access_is_big_endian(vdev)) { | |
116 | stq_be_p(ptr, v); | |
117 | } else { | |
118 | stq_le_p(ptr, v); | |
119 | } | |
120 | } | |
121 | ||
122 | static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr) | |
123 | { | |
124 | if (virtio_access_is_big_endian(vdev)) { | |
125 | return lduw_be_p(ptr); | |
126 | } else { | |
127 | return lduw_le_p(ptr); | |
128 | } | |
129 | } | |
130 | ||
131 | static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr) | |
132 | { | |
133 | if (virtio_access_is_big_endian(vdev)) { | |
134 | return ldl_be_p(ptr); | |
135 | } else { | |
136 | return ldl_le_p(ptr); | |
137 | } | |
138 | } | |
139 | ||
140 | static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr) | |
141 | { | |
142 | if (virtio_access_is_big_endian(vdev)) { | |
143 | return ldq_be_p(ptr); | |
144 | } else { | |
145 | return ldq_le_p(ptr); | |
146 | } | |
147 | } | |
148 | ||
149 | static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s) | |
150 | { | |
151 | #ifdef HOST_WORDS_BIGENDIAN | |
152 | return virtio_access_is_big_endian(vdev) ? s : bswap16(s); | |
153 | #else | |
154 | return virtio_access_is_big_endian(vdev) ? bswap16(s) : s; | |
155 | #endif | |
156 | } | |
157 | ||
e6a830d6 PB |
158 | static inline uint16_t virtio_lduw_phys_cached(VirtIODevice *vdev, |
159 | MemoryRegionCache *cache, | |
160 | hwaddr pa) | |
161 | { | |
162 | if (virtio_access_is_big_endian(vdev)) { | |
163 | return lduw_be_phys_cached(cache, pa); | |
164 | } | |
165 | return lduw_le_phys_cached(cache, pa); | |
166 | } | |
167 | ||
168 | static inline uint32_t virtio_ldl_phys_cached(VirtIODevice *vdev, | |
169 | MemoryRegionCache *cache, | |
170 | hwaddr pa) | |
171 | { | |
172 | if (virtio_access_is_big_endian(vdev)) { | |
173 | return ldl_be_phys_cached(cache, pa); | |
174 | } | |
175 | return ldl_le_phys_cached(cache, pa); | |
176 | } | |
177 | ||
178 | static inline uint64_t virtio_ldq_phys_cached(VirtIODevice *vdev, | |
179 | MemoryRegionCache *cache, | |
180 | hwaddr pa) | |
181 | { | |
182 | if (virtio_access_is_big_endian(vdev)) { | |
183 | return ldq_be_phys_cached(cache, pa); | |
184 | } | |
185 | return ldq_le_phys_cached(cache, pa); | |
186 | } | |
187 | ||
188 | static inline void virtio_stw_phys_cached(VirtIODevice *vdev, | |
189 | MemoryRegionCache *cache, | |
190 | hwaddr pa, uint16_t value) | |
191 | { | |
192 | if (virtio_access_is_big_endian(vdev)) { | |
193 | stw_be_phys_cached(cache, pa, value); | |
194 | } else { | |
195 | stw_le_phys_cached(cache, pa, value); | |
196 | } | |
197 | } | |
198 | ||
199 | static inline void virtio_stl_phys_cached(VirtIODevice *vdev, | |
200 | MemoryRegionCache *cache, | |
201 | hwaddr pa, uint32_t value) | |
202 | { | |
203 | if (virtio_access_is_big_endian(vdev)) { | |
204 | stl_be_phys_cached(cache, pa, value); | |
205 | } else { | |
206 | stl_le_phys_cached(cache, pa, value); | |
207 | } | |
208 | } | |
209 | ||
0f5d1d2a GK |
210 | static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s) |
211 | { | |
212 | *s = virtio_tswap16(vdev, *s); | |
213 | } | |
214 | ||
215 | static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s) | |
216 | { | |
217 | #ifdef HOST_WORDS_BIGENDIAN | |
218 | return virtio_access_is_big_endian(vdev) ? s : bswap32(s); | |
219 | #else | |
220 | return virtio_access_is_big_endian(vdev) ? bswap32(s) : s; | |
221 | #endif | |
222 | } | |
223 | ||
224 | static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s) | |
225 | { | |
226 | *s = virtio_tswap32(vdev, *s); | |
227 | } | |
228 | ||
229 | static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s) | |
230 | { | |
231 | #ifdef HOST_WORDS_BIGENDIAN | |
232 | return virtio_access_is_big_endian(vdev) ? s : bswap64(s); | |
233 | #else | |
234 | return virtio_access_is_big_endian(vdev) ? bswap64(s) : s; | |
235 | #endif | |
236 | } | |
237 | ||
238 | static inline void virtio_tswap64s(VirtIODevice *vdev, uint64_t *s) | |
239 | { | |
240 | *s = virtio_tswap64(vdev, *s); | |
241 | } | |
2a6a4076 | 242 | #endif /* QEMU_VIRTIO_ACCESS_H */ |