| 2 |
theseven |
1 |
//
|
|
|
2 |
//
|
|
|
3 |
// Copyright 2010 TheSeven
|
|
|
4 |
//
|
|
|
5 |
//
|
|
|
6 |
// This file is part of emBIOS.
|
|
|
7 |
//
|
|
|
8 |
// emBIOS is free software: you can redistribute it and/or
|
|
|
9 |
// modify it under the terms of the GNU General Public License as
|
|
|
10 |
// published by the Free Software Foundation, either version 2 of the
|
|
|
11 |
// License, or (at your option) any later version.
|
|
|
12 |
//
|
|
|
13 |
// emBIOS is distributed in the hope that it will be useful,
|
|
|
14 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
15 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
16 |
// See the GNU General Public License for more details.
|
|
|
17 |
//
|
|
|
18 |
// You should have received a copy of the GNU General Public License along
|
|
|
19 |
// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
|
|
20 |
//
|
|
|
21 |
//
|
|
|
22 |
|
|
|
23 |
|
|
|
24 |
#ifndef __UTIL_H__
|
|
|
25 |
#define __UTIL_H__
|
|
|
26 |
|
|
|
27 |
|
|
|
28 |
#include "global.h"
|
|
|
29 |
|
|
|
30 |
|
| 58 |
theseven |
31 |
#ifndef NULL
|
|
|
32 |
#define NULL ((void*)0)
|
| 2 |
theseven |
33 |
#endif
|
| 58 |
theseven |
34 |
|
|
|
35 |
#ifndef MIN
|
|
|
36 |
#define MIN(a, b) (((a)<(b))?(a):(b))
|
|
|
37 |
#endif
|
|
|
38 |
|
|
|
39 |
#ifndef MAX
|
|
|
40 |
#define MAX(a, b) (((a)>(b))?(a):(b))
|
|
|
41 |
#endif
|
|
|
42 |
|
|
|
43 |
/* return number of elements in array a */
|
|
|
44 |
#define ARRAYLEN(a) (sizeof(a)/sizeof((a)[0]))
|
|
|
45 |
|
|
|
46 |
/* return p incremented by specified number of bytes */
|
|
|
47 |
#define SKIPBYTES(p, count) ((typeof (p))((char *)(p) + (count)))
|
|
|
48 |
|
| 297 |
theseven |
49 |
#define BIT(x) (1 << (x))
|
|
|
50 |
#define BITRANGE(x, y) ((0xfffffffful >> (31 + (x) - (y))) << (x))
|
|
|
51 |
|
|
|
52 |
#define ERR_RC(val) (BIT(31) | (val))
|
| 336 |
theseven |
53 |
#define IS_ERR(val) (val & BIT(31))
|
| 297 |
theseven |
54 |
#define RET_ERR(val) \
|
|
|
55 |
{ \
|
|
|
56 |
return ERR_RC(val); \
|
|
|
57 |
}
|
|
|
58 |
#define RET_ERR_MTX(val, mutex) \
|
|
|
59 |
{ \
|
|
|
60 |
mutex_unlock(mutex); \
|
|
|
61 |
return ERR_RC(val); \
|
|
|
62 |
}
|
|
|
63 |
#define PASS_RC(expr, bits, val) \
|
|
|
64 |
{ \
|
| 336 |
theseven |
65 |
int PASS_RC_rc = (expr); \
|
|
|
66 |
if (IS_ERR(PASS_RC_rc)) \
|
|
|
67 |
return ERR_RC((PASS_RC_rc << (bits)) | (val)); \
|
| 297 |
theseven |
68 |
}
|
|
|
69 |
#define PASS_RC_MTX(expr, bits, val, mutex) \
|
|
|
70 |
{ \
|
| 336 |
theseven |
71 |
int PASS_RC_MTX_rc = (expr); \
|
|
|
72 |
if (IS_ERR(PASS_RC_MTX_rc)) \
|
| 297 |
theseven |
73 |
{ \
|
|
|
74 |
mutex_unlock(mutex); \
|
| 336 |
theseven |
75 |
return ERR_RC((PASS_RC_MTX_rc << (bits)) | (val)); \
|
| 297 |
theseven |
76 |
} \
|
|
|
77 |
}
|
|
|
78 |
|
| 58 |
theseven |
79 |
#define P2_M1(p2) ((1 << (p2))-1)
|
|
|
80 |
|
|
|
81 |
/* align up or down to nearest 2^p2 */
|
|
|
82 |
#define ALIGN_DOWN_P2(n, p2) ((n) & ~P2_M1(p2))
|
|
|
83 |
#define ALIGN_UP_P2(n, p2) ALIGN_DOWN_P2((n) + P2_M1(p2),p2)
|
|
|
84 |
|
|
|
85 |
/* align up or down to nearest integer multiple of a */
|
|
|
86 |
#define ALIGN_DOWN(n, a) ((n)/(a)*(a))
|
|
|
87 |
#define ALIGN_UP(n, a) ALIGN_DOWN((n)+((a)-1),a)
|
|
|
88 |
|
|
|
89 |
/* align start and end of buffer to nearest integer multiple of a */
|
|
|
90 |
#define ALIGN_BUFFER(ptr,len,align) \
|
|
|
91 |
{\
|
|
|
92 |
uintptr_t tmp_ptr1 = (uintptr_t)ptr; \
|
|
|
93 |
uintptr_t tmp_ptr2 = tmp_ptr1 + len;\
|
|
|
94 |
tmp_ptr1 = ALIGN_UP(tmp_ptr1,align); \
|
|
|
95 |
tmp_ptr2 = ALIGN_DOWN(tmp_ptr2,align); \
|
|
|
96 |
len = tmp_ptr2 - tmp_ptr1; \
|
|
|
97 |
ptr = (typeof(ptr))tmp_ptr1; \
|
|
|
98 |
}
|
|
|
99 |
|
|
|
100 |
|
|
|
101 |
/* live endianness conversion */
|
|
|
102 |
#ifdef LITTLE_ENDIAN
|
|
|
103 |
#define letoh16(x) (x)
|
|
|
104 |
#define letoh32(x) (x)
|
|
|
105 |
#define htole16(x) (x)
|
|
|
106 |
#define htole32(x) (x)
|
|
|
107 |
#define betoh16(x) swap16(x)
|
|
|
108 |
#define betoh32(x) swap32(x)
|
|
|
109 |
#define htobe16(x) swap16(x)
|
|
|
110 |
#define htobe32(x) swap32(x)
|
|
|
111 |
#define swap_odd_even_be32(x) (x)
|
|
|
112 |
#define swap_odd_even_le32(x) swap_odd_even32(x)
|
|
|
113 |
#else
|
|
|
114 |
#define letoh16(x) swap16(x)
|
|
|
115 |
#define letoh32(x) swap32(x)
|
|
|
116 |
#define htole16(x) swap16(x)
|
|
|
117 |
#define htole32(x) swap32(x)
|
|
|
118 |
#define betoh16(x) (x)
|
|
|
119 |
#define betoh32(x) (x)
|
|
|
120 |
#define htobe16(x) (x)
|
|
|
121 |
#define htobe32(x) (x)
|
|
|
122 |
#define swap_odd_even_be32(x) swap_odd_even32(x)
|
|
|
123 |
#define swap_odd_even_le32(x) (x)
|
|
|
124 |
#endif
|
|
|
125 |
|
|
|
126 |
|
|
|
127 |
/* static endianness conversion */
|
|
|
128 |
#define SWAP_16(x) ((typeof(x))(unsigned short)(((unsigned short)(x) >> 8) | \
|
|
|
129 |
((unsigned short)(x) << 8)))
|
|
|
130 |
|
|
|
131 |
#define SWAP_32(x) ((typeof(x))(unsigned long)( ((unsigned long)(x) >> 24) | \
|
|
|
132 |
(((unsigned long)(x) & 0xff0000ul) >> 8) | \
|
|
|
133 |
(((unsigned long)(x) & 0xff00ul) << 8) | \
|
|
|
134 |
((unsigned long)(x) << 24)))
|
|
|
135 |
|
|
|
136 |
#ifdef RLITTLE_ENDIAN
|
|
|
137 |
#define LE_TO_H16(x) (x)
|
|
|
138 |
#define LE_TO_H32(x) (x)
|
|
|
139 |
#define H_TO_LE16(x) (x)
|
|
|
140 |
#define H_TO_LE32(x) (x)
|
|
|
141 |
#define BE_TO_H16(x) SWAP_16(x)
|
|
|
142 |
#define BE_TO_H32(x) SWAP_32(x)
|
|
|
143 |
#define H_TO_BE16(x) SWAP_16(x)
|
|
|
144 |
#define H_TO_BE32(x) SWAP_32(x)
|
|
|
145 |
#else
|
|
|
146 |
#define LE_TO_H16(x) SWAP_16(x)
|
|
|
147 |
#define LE_TO_H32(x) SWAP_32(x)
|
|
|
148 |
#define H_TO_LE16(x) SWAP_16(x)
|
|
|
149 |
#define H_TO_LE32(x) SWAP_32(x)
|
|
|
150 |
#define BE_TO_H16(x) (x)
|
|
|
151 |
#define BE_TO_H32(x) (x)
|
|
|
152 |
#define H_TO_BE16(x) (x)
|
|
|
153 |
#define H_TO_BE32(x) (x)
|
|
|
154 |
#endif
|
|
|
155 |
|
|
|
156 |
/* Get the byte offset of a type's member */
|
|
|
157 |
#define OFFSETOF(type, membername) ((off_t)&((type *)0)->membername)
|
|
|
158 |
|
|
|
159 |
/* Get the type pointer from one of its members */
|
|
|
160 |
#define TYPE_FROM_MEMBER(type, memberptr, membername) \
|
|
|
161 |
((type *)((intptr_t)(memberptr) - OFFSETOF(type, membername)))
|
|
|
162 |
|
|
|
163 |
static inline uint16_t swap16(uint16_t value)
|
|
|
164 |
/*
|
|
|
165 |
result[15..8] = value[ 7..0];
|
|
|
166 |
result[ 7..0] = value[15..8];
|
|
|
167 |
*/
|
|
|
168 |
{
|
|
|
169 |
return (value >> 8) | (value << 8);
|
|
|
170 |
}
|
|
|
171 |
|
|
|
172 |
static inline uint32_t swap32(uint32_t value)
|
|
|
173 |
/*
|
|
|
174 |
result[31..24] = value[ 7.. 0];
|
|
|
175 |
result[23..16] = value[15.. 8];
|
|
|
176 |
result[15.. 8] = value[23..16];
|
|
|
177 |
result[ 7.. 0] = value[31..24];
|
|
|
178 |
*/
|
|
|
179 |
{
|
|
|
180 |
uint32_t hi = swap16(value >> 16);
|
|
|
181 |
uint32_t lo = swap16(value & 0xffff);
|
|
|
182 |
return (lo << 16) | hi;
|
|
|
183 |
}
|
|
|
184 |
|
|
|
185 |
static inline uint32_t swap_odd_even32(uint32_t value)
|
|
|
186 |
{
|
|
|
187 |
/*
|
|
|
188 |
result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
|
|
|
189 |
result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
|
|
|
190 |
*/
|
|
|
191 |
uint32_t t = value & 0xff00ff00;
|
|
|
192 |
return (t >> 8) | ((t ^ value) << 8);
|
|
|
193 |
}
|
|
|
194 |
|
|
|
195 |
#ifndef BIT_N
|
|
|
196 |
#define BIT_N(n) (1U << (n))
|
|
|
197 |
#endif
|
|
|
198 |
|
|
|
199 |
#ifndef CACHEALIGN_SIZE /* could be elsewhere for a particular reason */
|
|
|
200 |
#ifdef CACHEALIGN_BITS
|
|
|
201 |
/* 2^CACHEALIGN_BITS = the byte size */
|
|
|
202 |
#define CACHEALIGN_SIZE (1u << CACHEALIGN_BITS)
|
|
|
203 |
#else
|
|
|
204 |
#define CACHEALIGN_SIZE 16 /* FIXME */
|
|
|
205 |
#endif
|
|
|
206 |
#endif /* CACHEALIGN_SIZE */
|
|
|
207 |
|
|
|
208 |
#define CACHEALIGN_ATTR __attribute__((aligned(CACHEALIGN_SIZE)))
|
|
|
209 |
/* Aligns x up to a CACHEALIGN_SIZE boundary */
|
|
|
210 |
#define CACHEALIGN_UP(x) \
|
|
|
211 |
((typeof (x))ALIGN_UP_P2((uintptr_t)(x), CACHEALIGN_BITS))
|
|
|
212 |
/* Aligns x down to a CACHEALIGN_SIZE boundary */
|
|
|
213 |
#define CACHEALIGN_DOWN(x) \
|
|
|
214 |
((typeof (x))ALIGN_DOWN_P2((uintptr_t)(x), CACHEALIGN_BITS))
|
|
|
215 |
/* Aligns at least to the greater of size x or CACHEALIGN_SIZE */
|
|
|
216 |
#define CACHEALIGN_AT_LEAST_ATTR(x) \
|
|
|
217 |
__attribute__((aligned(CACHEALIGN_UP(x))))
|
|
|
218 |
/* Aligns a buffer pointer and size to proper boundaries */
|
|
|
219 |
#define CACHEALIGN_BUFFER(start, size) \
|
|
|
220 |
ALIGN_BUFFER((start), (size), CACHEALIGN_SIZE)
|
|
|
221 |
|
|
|
222 |
/* Double-cast to avoid 'dereferencing type-punned pointer will
|
|
|
223 |
* break strict aliasing rules' B.S. */
|
|
|
224 |
#define PUN_PTR(type, p) ((type)(intptr_t)(p))
|
|
|
225 |
|
|
|
226 |
|
|
|
227 |
#endif
|