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
|
/* Public domain. */
#ifndef _LINUXKPI_LINUX_IOSYS_MAP_H
#define _LINUXKPI_LINUX_IOSYS_MAP_H
#include <linux/io.h>
#include <linux/string.h>
struct iosys_map {
union {
void *vaddr_iomem;
void *vaddr;
};
bool is_iomem;
#ifdef __OpenBSD__
bus_space_handle_t bsh;
bus_size_t size;
#endif
};
#define IOSYS_MAP_INIT_OFFSET(_ism_src_p, _off) ({ \
struct iosys_map ism_dst = *(_ism_src_p); \
iosys_map_incr(&ism_dst, _off); \
ism_dst; \
})
static inline void
iosys_map_incr(struct iosys_map *ism, size_t n)
{
if (ism->is_iomem)
ism->vaddr_iomem += n;
else
ism->vaddr += n;
}
static inline void
iosys_map_memcpy_to(struct iosys_map *ism, size_t off, const void *src,
size_t len)
{
if (ism->is_iomem)
memcpy_toio(ism->vaddr_iomem + off, src, len);
else
memcpy(ism->vaddr + off, src, len);
}
static inline bool
iosys_map_is_null(const struct iosys_map *ism)
{
if (ism->is_iomem)
return (ism->vaddr_iomem == NULL);
else
return (ism->vaddr == NULL);
}
static inline bool
iosys_map_is_set(const struct iosys_map *ism)
{
if (ism->is_iomem)
return (ism->vaddr_iomem != NULL);
else
return (ism->vaddr != NULL);
}
static inline bool
iosys_map_is_equal(const struct iosys_map *ism_a,
const struct iosys_map *ism_b)
{
if (ism_a->is_iomem != ism_b->is_iomem)
return (false);
if (ism_a->is_iomem)
return (ism_a->vaddr_iomem == ism_b->vaddr_iomem);
else
return (ism_a->vaddr == ism_b->vaddr);
}
static inline void
iosys_map_clear(struct iosys_map *ism)
{
if (ism->is_iomem) {
ism->vaddr_iomem = NULL;
ism->is_iomem = false;
} else {
ism->vaddr = NULL;
}
}
static inline void
iosys_map_set_vaddr_iomem(struct iosys_map *ism, void *addr)
{
ism->vaddr_iomem = addr;
ism->is_iomem = true;
}
static inline void
iosys_map_set_vaddr(struct iosys_map *ism, void *addr)
{
ism->vaddr = addr;
ism->is_iomem = false;
}
static inline void
iosys_map_memset(struct iosys_map *ism, size_t off, int value, size_t len)
{
if (ism->is_iomem)
memset_io(ism->vaddr_iomem + off, value, len);
else
memset(ism->vaddr + off, value, len);
}
#ifdef __LP64__
#define _iosys_map_readq(_addr) readq(_addr)
#define _iosys_map_writeq(_val, _addr) writeq(_val, _addr)
#else
#define _iosys_map_readq(_addr) ({ \
uint64_t val; \
memcpy_fromio(&val, _addr, sizeof(uint64_t)); \
val; \
})
#define _iosys_map_writeq(_val, _addr) \
memcpy_toio(_addr, &(_val), sizeof(uint64_t))
#endif
#define iosys_map_rd(_ism, _off, _type) ({ \
_type val; \
if ((_ism)->is_iomem) { \
void *addr = (_ism)->vaddr_iomem + (_off); \
val = _Generic(val, \
uint8_t : readb(addr), \
uint16_t: readw(addr), \
uint32_t: readl(addr), \
uint64_t: _iosys_map_readq(addr)); \
} else \
val = READ_ONCE(*(_type *)((_ism)->vaddr + (_off))); \
val; \
})
#define iosys_map_wr(_ism, _off, _type, _val) ({ \
_type val = (_val); \
if ((_ism)->is_iomem) { \
void *addr = (_ism)->vaddr_iomem + (_off); \
_Generic(val, \
uint8_t : writeb(val, addr), \
uint16_t: writew(val, addr), \
uint32_t: writel(val, addr), \
uint64_t: _iosys_map_writeq(val, addr)); \
} else \
WRITE_ONCE(*(_type *)((_ism)->vaddr + (_off)), val); \
})
#define iosys_map_rd_field(_ism, _off, _type, _field) ({ \
_type *s; \
iosys_map_rd(_ism, (_off) + offsetof(_type, _field), \
__typeof(s->_field)); \
})
#define iosys_map_wr_field(_ism, _off, _type, _field, _val) ({ \
_type *s; \
iosys_map_wr(_ism, (_off) + offsetof(_type, _field), \
__typeof(s->_field), _val); \
})
#endif
|