Initial import in Tizen
[profile/ivi/flashrom.git] / hwaccess.h
1 /*
2  * This file is part of the flashrom project.
3  *
4  * Copyright (C) 2009 Carl-Daniel Hailfinger
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  */
19
20 /*
21  * Header file for hardware access and OS abstraction. Included from flash.h.
22  */
23
24 #ifndef __HWACCESS_H__
25 #define __HWACCESS_H__ 1
26
27 #if defined (__i386__) || defined (__x86_64__)
28 #if defined(__GLIBC__)
29 #include <sys/io.h>
30 #endif
31 #endif
32
33 #if NEED_PCI == 1
34 /*
35  * libpci headers use the variable name "index" which triggers shadowing
36  * warnings on systems which have the index() function in a default #include
37  * or as builtin.
38  */
39 #define index shadow_workaround_index
40 #include <pci/pci.h>
41 #undef index
42 #endif
43
44 #if defined (__i386__) || defined (__x86_64__)
45
46 /* All x86 is little-endian. */
47 #define __FLASHROM_LITTLE_ENDIAN__ 1
48
49 #elif defined (__mips) || defined (__mips__) || defined (_mips) || defined (mips)
50
51 /* MIPS can be either endian. */
52 #if defined (__MIPSEL) || defined (__MIPSEL__) || defined (_MIPSEL) || defined (MIPSEL)
53 #define __FLASHROM_LITTLE_ENDIAN__ 1
54 #elif defined (__MIPSEB) || defined (__MIPSEB__) || defined (_MIPSEB) || defined (MIPSEB)
55 #define __FLASHROM_BIG_ENDIAN__ 1
56 #endif
57
58 #elif defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || defined(__ppc64__)
59
60 /* PowerPC can be either endian. */
61 #if defined (_BIG_ENDIAN) || defined (__BIG_ENDIAN__)
62 #define __FLASHROM_BIG_ENDIAN__ 1
63 /* Error checking in case some weird header has #defines for LE as well. */
64 #if defined (_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__)
65 #error Conflicting endianness #define
66 #endif
67 #else
68 #error Little-endian PowerPC #defines are unknown
69 #endif
70
71 #elif defined (__arm__)
72 #if defined (__ARMEL__)
73 #define __FLASHROM_LITTLE_ENDIAN__ 1
74 #else
75 #error Big-endian ARM #defines are unknown
76 #endif
77
78 #endif
79
80 #if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__)
81 /* Nonstandard libc-specific macros for determining endianness. */
82 #if defined(__GLIBC__)
83 #include <endian.h>
84 #if BYTE_ORDER == LITTLE_ENDIAN
85 #define __FLASHROM_LITTLE_ENDIAN__ 1
86 #elif BYTE_ORDER == BIG_ENDIAN
87 #define __FLASHROM_BIG_ENDIAN__ 1
88 #endif
89 #endif
90 #endif
91
92 #if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__)
93 #error Unable to determine endianness. Please add support for your arch or libc.
94 #endif
95
96 #define ___constant_swab8(x) ((uint8_t) (                               \
97         (((uint8_t)(x) & (uint8_t)0xffU))))
98
99 #define ___constant_swab16(x) ((uint16_t) (                             \
100         (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) |                    \
101         (((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
102
103 #define ___constant_swab32(x) ((uint32_t) (                             \
104         (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) |              \
105         (((uint32_t)(x) & (uint32_t)0x0000ff00UL) <<  8) |              \
106         (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >>  8) |              \
107         (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
108
109 #define ___constant_swab64(x) ((uint64_t) (                             \
110         (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) |     \
111         (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) |     \
112         (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) |     \
113         (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) <<  8) |     \
114         (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >>  8) |     \
115         (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) |     \
116         (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) |     \
117         (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56)))
118
119 #if defined (__FLASHROM_BIG_ENDIAN__)
120
121 #define cpu_to_le(bits)                                                 \
122 static inline uint##bits##_t cpu_to_le##bits(uint##bits##_t val)        \
123 {                                                                       \
124         return ___constant_swab##bits(val);                             \
125 }
126
127 cpu_to_le(8)
128 cpu_to_le(16)
129 cpu_to_le(32)
130 cpu_to_le(64)
131
132 #define cpu_to_be8
133 #define cpu_to_be16
134 #define cpu_to_be32
135 #define cpu_to_be64
136
137 #elif defined (__FLASHROM_LITTLE_ENDIAN__)
138
139 #define cpu_to_be(bits)                                                 \
140 static inline uint##bits##_t cpu_to_be##bits(uint##bits##_t val)        \
141 {                                                                       \
142         return ___constant_swab##bits(val);                             \
143 }
144
145 cpu_to_be(8)
146 cpu_to_be(16)
147 cpu_to_be(32)
148 cpu_to_be(64)
149
150 #define cpu_to_le8
151 #define cpu_to_le16
152 #define cpu_to_le32
153 #define cpu_to_le64
154
155 #else
156
157 #error Could not determine endianness.
158
159 #endif
160
161 #define be_to_cpu8 cpu_to_be8
162 #define be_to_cpu16 cpu_to_be16
163 #define be_to_cpu32 cpu_to_be32
164 #define be_to_cpu64 cpu_to_be64
165 #define le_to_cpu8 cpu_to_le8
166 #define le_to_cpu16 cpu_to_le16
167 #define le_to_cpu32 cpu_to_le32
168 #define le_to_cpu64 cpu_to_le64
169
170 #if NEED_PCI == 1
171 #if defined (__i386__) || defined (__x86_64__)
172
173 #define __FLASHROM_HAVE_OUTB__ 1
174
175 /* for iopl and outb under Solaris */
176 #if defined (__sun) && (defined(__i386) || defined(__amd64))
177 #include <strings.h>
178 #include <sys/sysi86.h>
179 #include <sys/psw.h>
180 #include <asm/sunddi.h>
181 #endif
182
183 #if (defined(__MACH__) && defined(__APPLE__))
184 #define __DARWIN__
185 #endif
186
187 /* Clarification about OUTB/OUTW/OUTL argument order:
188  * OUT[BWL](val, port)
189  */
190
191 #if defined(__FreeBSD__) || defined(__DragonFly__)
192   /* Note that Debian/kFreeBSD (FreeBSD kernel with glibc) has conflicting
193    * out[bwl] definitions in machine/cpufunc.h and sys/io.h at least in some
194    * versions. Use machine/cpufunc.h only for plain FreeBSD/DragonFlyBSD.
195    */
196   #include <machine/cpufunc.h>
197   #define off64_t off_t
198   #define lseek64 lseek
199   #define OUTB(x, y) do { u_int outb_tmp = (y); outb(outb_tmp, (x)); } while (0)
200   #define OUTW(x, y) do { u_int outw_tmp = (y); outw(outw_tmp, (x)); } while (0)
201   #define OUTL(x, y) do { u_int outl_tmp = (y); outl(outl_tmp, (x)); } while (0)
202   #define INB(x) __extension__ ({ u_int inb_tmp = (x); inb(inb_tmp); })
203   #define INW(x) __extension__ ({ u_int inw_tmp = (x); inw(inw_tmp); })
204   #define INL(x) __extension__ ({ u_int inl_tmp = (x); inl(inl_tmp); })
205 #else
206 #if defined(__DARWIN__)
207     /* Header is part of the DirectHW library. */
208     #include <DirectHW/DirectHW.h>
209     #define off64_t off_t
210     #define lseek64 lseek
211 #endif
212 #if defined (__sun) && (defined(__i386) || defined(__amd64))
213   /* Note different order for outb */
214   #define OUTB(x,y) outb(y, x)
215   #define OUTW(x,y) outw(y, x)
216   #define OUTL(x,y) outl(y, x)
217   #define INB  inb
218   #define INW  inw
219   #define INL  inl
220 #else
221
222 #ifdef __DJGPP__
223
224 #include <pc.h>
225
226   #define OUTB(x,y) outportb(y, x)
227   #define OUTW(x,y) outportw(y, x)
228   #define OUTL(x,y) outportl(y, x)
229
230   #define INB  inportb
231   #define INW  inportw
232   #define INL  inportl
233
234 #else
235   /* This is the usual glibc interface. */
236   #define OUTB outb
237   #define OUTW outw
238   #define OUTL outl
239   #define INB  inb
240   #define INW  inw
241   #define INL  inl
242
243 #endif
244
245 #endif
246 #endif
247
248 #if defined(__NetBSD__) || defined (__OpenBSD__)
249   #define off64_t off_t
250   #define lseek64 lseek
251   #if defined(__i386__) || defined(__x86_64__)
252     #include <sys/types.h>
253     #include <machine/sysarch.h>
254 #if defined(__NetBSD__)
255     #if defined(__i386__)
256       #define iopl i386_iopl
257     #elif defined(__x86_64__)
258       #define iopl x86_64_iopl
259     #endif
260 #elif defined (__OpenBSD__)
261     #if defined(__i386__)
262       #define iopl i386_iopl
263     #elif defined(__amd64__)
264       #define iopl amd64_iopl
265     #endif
266 #endif
267
268 static inline void outb(uint8_t value, uint16_t port)
269 {
270         asm volatile ("outb %b0,%w1": :"a" (value), "Nd" (port));
271 }
272
273 static inline uint8_t inb(uint16_t port)
274 {
275         uint8_t value;
276         asm volatile ("inb %w1,%0":"=a" (value):"Nd" (port));
277         return value;
278 }
279
280 static inline void outw(uint16_t value, uint16_t port)
281 {
282         asm volatile ("outw %w0,%w1": :"a" (value), "Nd" (port));
283 }
284
285 static inline uint16_t inw(uint16_t port)
286 {
287         uint16_t value;
288         asm volatile ("inw %w1,%0":"=a" (value):"Nd" (port));
289         return value;
290 }
291
292 static inline void outl(uint32_t value, uint16_t port)
293 {
294         asm volatile ("outl %0,%w1": :"a" (value), "Nd" (port));
295 }
296
297 static inline uint32_t inl(uint16_t port)
298 {
299         uint32_t value;
300         asm volatile ("inl %1,%0":"=a" (value):"Nd" (port));
301         return value;
302 }
303   #endif
304 #endif
305
306 #if !defined(__DARWIN__) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && !defined(__DragonFly__) && !defined(__LIBPAYLOAD__)
307 typedef struct { uint32_t hi, lo; } msr_t;
308 msr_t rdmsr(int addr);
309 int wrmsr(int addr, msr_t msr);
310 #endif
311 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
312 /* FreeBSD already has conflicting definitions for wrmsr/rdmsr. */
313 #undef rdmsr
314 #undef wrmsr
315 #define rdmsr freebsd_rdmsr
316 #define wrmsr freebsd_wrmsr
317 typedef struct { uint32_t hi, lo; } msr_t;
318 msr_t freebsd_rdmsr(int addr);
319 int freebsd_wrmsr(int addr, msr_t msr);
320 #endif
321 #if defined(__LIBPAYLOAD__)
322 #include <arch/io.h>
323 #include <arch/msr.h>
324 typedef struct { uint32_t hi, lo; } msr_t;
325 msr_t libpayload_rdmsr(int addr);
326 int libpayload_wrmsr(int addr, msr_t msr);
327 #undef rdmsr
328 #define rdmsr libpayload_rdmsr
329 #define wrmsr libpayload_wrmsr
330 #endif
331
332 #elif defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || defined(__ppc64__)
333
334 /* PCI port I/O is not yet implemented on PowerPC. */
335
336 #elif defined (__mips) || defined (__mips__) || defined (_mips) || defined (mips)
337
338 /* PCI port I/O is not yet implemented on MIPS. */
339
340 #elif defined(__arm__)
341
342 /* Non memory mapped I/O is not supported on ARM. */
343
344 #else
345
346 #error Unknown architecture, please check if it supports PCI port IO.
347
348 #endif
349 #endif
350
351 #endif /* !__HWACCESS_H__ */