libmetal
Loading...
Searching...
No Matches
io.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015 - 2017, Xilinx Inc. and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7/*
8 * @file io.h
9 * @brief I/O access primitives for libmetal.
10 */
11
12#ifndef __METAL_IO__H__
13#define __METAL_IO__H__
14
15#include <limits.h>
16#include <stdint.h>
17#include <string.h>
18#include <stdlib.h>
19#include <metal/assert.h>
20#include <metal/compiler.h>
21#include <metal/atomic.h>
22#include <metal/sys.h>
23#include <metal/cpu.h>
24
25#ifdef __cplusplus
26extern "C" {
27#endif
28
32
33#ifdef __MICROBLAZE__
34#define NO_ATOMIC_64_SUPPORT
35#endif
36
37struct metal_io_region;
38
41 uint64_t (*read)(struct metal_io_region *io,
42 unsigned long offset,
43 memory_order order,
44 int width);
45 void (*write)(struct metal_io_region *io,
46 unsigned long offset,
47 uint64_t value,
48 memory_order order,
49 int width);
50 int (*block_read)(struct metal_io_region *io,
51 unsigned long offset,
52 void *restrict dst,
53 memory_order order,
54 int len);
55 int (*block_write)(struct metal_io_region *io,
56 unsigned long offset,
57 const void *restrict src,
58 memory_order order,
59 int len);
60 void (*block_set)(struct metal_io_region *io,
61 unsigned long offset,
62 unsigned char value,
63 memory_order order,
64 int len);
65 void (*close)(struct metal_io_region *io);
67 unsigned long offset);
68 unsigned long (*phys_to_offset)(struct metal_io_region *io,
70};
71
85
97void
98metal_io_init(struct metal_io_region *io, void *virt,
99 const metal_phys_addr_t *physmap, size_t size,
100 unsigned int page_shift, unsigned int mem_flags,
101 const struct metal_io_ops *ops);
102
107static inline void metal_io_finish(struct metal_io_region *io)
108{
109 if (io->ops.close)
110 (*io->ops.close)(io);
111 memset(io, 0, sizeof(*io));
112}
113
120static inline size_t metal_io_region_size(struct metal_io_region *io)
121{
122 return io->size;
123}
124
131static inline void *
132metal_io_virt(struct metal_io_region *io, unsigned long offset)
133{
134 return (io->virt != METAL_BAD_VA && offset < io->size
135 ? (void *)((uintptr_t)io->virt + offset)
136 : NULL);
137}
138
145static inline unsigned long
147{
148 size_t offset = (uintptr_t)virt - (uintptr_t)io->virt;
149
150 return (offset < io->size ? offset : METAL_BAD_OFFSET);
151}
152
160static inline metal_phys_addr_t
161metal_io_phys(struct metal_io_region *io, unsigned long offset)
162{
163 if (!io->ops.offset_to_phys) {
164 unsigned long page = (io->page_shift >=
165 sizeof(offset) * CHAR_BIT ?
166 0 : offset >> io->page_shift);
167 return (io->physmap && offset < io->size
168 ? io->physmap[page] + (offset & io->page_mask)
170 }
171
172 return io->ops.offset_to_phys(io, offset);
173}
174
181static inline unsigned long
183{
184 if (!io->ops.phys_to_offset) {
185 unsigned long offset =
186 (io->page_mask == (metal_phys_addr_t)(-1) ?
187 phys - io->physmap[0] : phys & io->page_mask);
188 do {
189 if (metal_io_phys(io, offset) == phys)
190 return offset;
191 offset += io->page_mask + 1;
192 } while (offset < io->size);
193 return METAL_BAD_OFFSET;
194 }
195
196 return (*io->ops.phys_to_offset)(io, phys);
197}
198
205static inline void *
210
218static inline metal_phys_addr_t
220{
221 return metal_io_phys(io, metal_io_virt_to_offset(io, virt));
222}
223
234static inline uint64_t
235metal_io_read(struct metal_io_region *io, unsigned long offset,
236 memory_order order, int width)
237{
238 void *ptr = metal_io_virt(io, offset);
239
240 if (io->ops.read)
241 return (*io->ops.read)(io, offset, order, width);
242 else if (ptr && sizeof(atomic_uchar) == width)
243 return atomic_load_explicit((atomic_uchar *)ptr, order);
244 else if (ptr && sizeof(atomic_ushort) == width)
245 return atomic_load_explicit((atomic_ushort *)ptr, order);
246 else if (ptr && sizeof(atomic_uint) == width)
247 return atomic_load_explicit((atomic_uint *)ptr, order);
248 else if (ptr && sizeof(atomic_ulong) == width)
249 return atomic_load_explicit((atomic_ulong *)ptr, order);
250#ifndef NO_ATOMIC_64_SUPPORT
251 else if (ptr && sizeof(atomic_ullong) == width)
252 return atomic_load_explicit((atomic_ullong *)ptr, order);
253#endif
254 metal_assert(0);
255 return 0; /* quiet compiler */
256}
257
268static inline void
269metal_io_write(struct metal_io_region *io, unsigned long offset,
270 uint64_t value, memory_order order, int width)
271{
272 void *ptr = metal_io_virt(io, offset);
273
274 if (io->ops.write)
275 (*io->ops.write)(io, offset, value, order, width);
276 else if (ptr && sizeof(atomic_uchar) == width)
277 atomic_store_explicit((atomic_uchar *)ptr, (unsigned char)value,
278 order);
279 else if (ptr && sizeof(atomic_ushort) == width)
281 (unsigned short)value, order);
282 else if (ptr && sizeof(atomic_uint) == width)
283 atomic_store_explicit((atomic_uint *)ptr, (unsigned int)value,
284 order);
285 else if (ptr && sizeof(atomic_ulong) == width)
286 atomic_store_explicit((atomic_ulong *)ptr, (unsigned long)value,
287 order);
288#ifndef NO_ATOMIC_64_SUPPORT
289 else if (ptr && sizeof(atomic_ullong) == width)
291 (unsigned long long)value, order);
292#endif
293 else
294 metal_assert(0);
295}
296
297#define metal_io_read8_explicit(_io, _ofs, _order) \
298 metal_io_read((_io), (_ofs), (_order), 1)
299#define metal_io_read8(_io, _ofs) \
300 metal_io_read((_io), (_ofs), memory_order_seq_cst, 1)
301#define metal_io_write8_explicit(_io, _ofs, _val, _order) \
302 metal_io_write((_io), (_ofs), (_val), (_order), 1)
303#define metal_io_write8(_io, _ofs, _val) \
304 metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 1)
305
306#define metal_io_read16_explicit(_io, _ofs, _order) \
307 metal_io_read((_io), (_ofs), (_order), 2)
308#define metal_io_read16(_io, _ofs) \
309 metal_io_read((_io), (_ofs), memory_order_seq_cst, 2)
310#define metal_io_write16_explicit(_io, _ofs, _val, _order) \
311 metal_io_write((_io), (_ofs), (_val), (_order), 2)
312#define metal_io_write16(_io, _ofs, _val) \
313 metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 2)
314
315#define metal_io_read32_explicit(_io, _ofs, _order) \
316 metal_io_read((_io), (_ofs), (_order), 4)
317#define metal_io_read32(_io, _ofs) \
318 metal_io_read((_io), (_ofs), memory_order_seq_cst, 4)
319#define metal_io_write32_explicit(_io, _ofs, _val, _order) \
320 metal_io_write((_io), (_ofs), (_val), (_order), 4)
321#define metal_io_write32(_io, _ofs, _val) \
322 metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 4)
323
324#define metal_io_read64_explicit(_io, _ofs, _order) \
325 metal_io_read((_io), (_ofs), (_order), 8)
326#define metal_io_read64(_io, _ofs) \
327 metal_io_read((_io), (_ofs), memory_order_seq_cst, 8)
328#define metal_io_write64_explicit(_io, _ofs, _val, _order) \
329 metal_io_write((_io), (_ofs), (_val), (_order), 8)
330#define metal_io_write64(_io, _ofs, _val) \
331 metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 8)
332
341int metal_io_block_read(struct metal_io_region *io, unsigned long offset,
342 void *restrict dst, int len);
343
352int metal_io_block_write(struct metal_io_region *io, unsigned long offset,
353 const void *restrict src, int len);
354
363int metal_io_block_set(struct metal_io_region *io, unsigned long offset,
364 unsigned char value, int len);
365
367
368#ifdef __cplusplus
369}
370#endif
371
372#include <metal/system/@PROJECT_SYSTEM@/io.h>
373
374#endif /* __METAL_IO__H__ */
#define metal_assert(cond)
Assertion macro.
Definition assert.h:21
memory_order
Definition atomic.h:35
unsigned long long atomic_ullong
Definition atomic.h:30
unsigned char atomic_uchar
Definition atomic.h:21
unsigned int atomic_uint
Definition atomic.h:25
unsigned short atomic_ushort
Definition atomic.h:23
unsigned long atomic_ulong
Definition atomic.h:28
#define atomic_load_explicit(OBJ, MO)
Definition atomic.h:62
#define atomic_store_explicit(OBJ, VAL, MO)
Definition atomic.h:58
#define restrict
Definition compiler.h:19
static uint64_t metal_io_read(struct metal_io_region *io, unsigned long offset, memory_order order, int width)
Read a value from an I/O region.
Definition io.h:235
int metal_io_block_write(struct metal_io_region *io, unsigned long offset, const void *restrict src, int len)
Write a block into an I/O region.
Definition io.c:72
static size_t metal_io_region_size(struct metal_io_region *io)
Get size of I/O region.
Definition io.h:120
void metal_io_init(struct metal_io_region *io, void *virt, const metal_phys_addr_t *physmap, size_t size, unsigned int page_shift, unsigned int mem_flags, const struct metal_io_ops *ops)
Open a libmetal I/O region.
Definition io.c:12
int metal_io_block_read(struct metal_io_region *io, unsigned long offset, void *restrict dst, int len)
Read a block from an I/O region.
Definition io.c:35
static void * metal_io_virt(struct metal_io_region *io, unsigned long offset)
Get virtual address for a given offset into the I/O region.
Definition io.h:132
static metal_phys_addr_t metal_io_virt_to_phys(struct metal_io_region *io, void *virt)
Convert a virtual address to physical address.
Definition io.h:219
static void metal_io_write(struct metal_io_region *io, unsigned long offset, uint64_t value, memory_order order, int width)
Write a value into an I/O region.
Definition io.h:269
static void * metal_io_phys_to_virt(struct metal_io_region *io, metal_phys_addr_t phys)
Convert a physical address to virtual address.
Definition io.h:206
static metal_phys_addr_t metal_io_phys(struct metal_io_region *io, unsigned long offset)
Get physical address for a given offset into the I/O region.
Definition io.h:161
static void metal_io_finish(struct metal_io_region *io)
Close a libmetal shared memory segment.
Definition io.h:107
static unsigned long metal_io_phys_to_offset(struct metal_io_region *io, metal_phys_addr_t phys)
Convert a physical address to offset within I/O region.
Definition io.h:182
static unsigned long metal_io_virt_to_offset(struct metal_io_region *io, void *virt)
Convert a virtual address to offset within I/O region.
Definition io.h:146
int metal_io_block_set(struct metal_io_region *io, unsigned long offset, unsigned char value, int len)
fill a block of an I/O region.
Definition io.c:109
#define METAL_BAD_VA
Definition sys.h:42
#define METAL_BAD_OFFSET
Definition sys.h:36
#define METAL_BAD_PHYS
Definition sys.h:39
unsigned long metal_phys_addr_t
Definition sys.h:30
Definition io.h:40
void(* close)(struct metal_io_region *io)
Definition io.h:65
void(* write)(struct metal_io_region *io, unsigned long offset, uint64_t value, memory_order order, int width)
Definition io.h:45
uint64_t(* read)(struct metal_io_region *io, unsigned long offset, memory_order order, int width)
Definition io.h:41
unsigned long(* phys_to_offset)(struct metal_io_region *io, metal_phys_addr_t phys)
Definition io.h:68
metal_phys_addr_t(* offset_to_phys)(struct metal_io_region *io, unsigned long offset)
Definition io.h:66
int(* block_write)(struct metal_io_region *io, unsigned long offset, const void *restrict src, memory_order order, int len)
Definition io.h:55
int(* block_read)(struct metal_io_region *io, unsigned long offset, void *restrict dst, memory_order order, int len)
Definition io.h:50
void(* block_set)(struct metal_io_region *io, unsigned long offset, unsigned char value, memory_order order, int len)
Definition io.h:60
Definition io.h:73
const metal_phys_addr_t * physmap
Definition io.h:75
size_t size
Definition io.h:78
unsigned int mem_flags
Definition io.h:81
unsigned long page_shift
Definition io.h:79
struct metal_io_ops ops
Definition io.h:83
void * virt
Definition io.h:74
metal_phys_addr_t page_mask
Definition io.h:80