2 * This file is part of the flashrom project.
4 * Copyright (C) 2009 Carl-Daniel Hailfinger
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.
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.
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
21 * Header file for hardware access and OS abstraction. Included from flash.h.
24 #ifndef __HWACCESS_H__
25 #define __HWACCESS_H__ 1
27 #if defined (__i386__) || defined (__x86_64__)
28 #if defined(__GLIBC__)
35 * libpci headers use the variable name "index" which triggers shadowing
36 * warnings on systems which have the index() function in a default #include
39 #define index shadow_workaround_index
44 #if defined (__i386__) || defined (__x86_64__)
46 /* All x86 is little-endian. */
47 #define __FLASHROM_LITTLE_ENDIAN__ 1
49 #elif defined (__mips) || defined (__mips__) || defined (_mips) || defined (mips)
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
58 #elif defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || defined(__ppc64__)
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
68 #error Little-endian PowerPC #defines are unknown
71 #elif defined (__arm__)
72 #if defined (__ARMEL__)
73 #define __FLASHROM_LITTLE_ENDIAN__ 1
75 #error Big-endian ARM #defines are unknown
80 #if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__)
81 /* Nonstandard libc-specific macros for determining endianness. */
82 #if defined(__GLIBC__)
84 #if BYTE_ORDER == LITTLE_ENDIAN
85 #define __FLASHROM_LITTLE_ENDIAN__ 1
86 #elif BYTE_ORDER == BIG_ENDIAN
87 #define __FLASHROM_BIG_ENDIAN__ 1
92 #if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__)
93 #error Unable to determine endianness. Please add support for your arch or libc.
96 #define ___constant_swab8(x) ((uint8_t) ( \
97 (((uint8_t)(x) & (uint8_t)0xffU))))
99 #define ___constant_swab16(x) ((uint16_t) ( \
100 (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
101 (((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
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)))
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)))
119 #if defined (__FLASHROM_BIG_ENDIAN__)
121 #define cpu_to_le(bits) \
122 static inline uint##bits##_t cpu_to_le##bits(uint##bits##_t val) \
124 return ___constant_swab##bits(val); \
137 #elif defined (__FLASHROM_LITTLE_ENDIAN__)
139 #define cpu_to_be(bits) \
140 static inline uint##bits##_t cpu_to_be##bits(uint##bits##_t val) \
142 return ___constant_swab##bits(val); \
157 #error Could not determine endianness.
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
171 #if defined (__i386__) || defined (__x86_64__)
173 #define __FLASHROM_HAVE_OUTB__ 1
175 /* for iopl and outb under Solaris */
176 #if defined (__sun) && (defined(__i386) || defined(__amd64))
178 #include <sys/sysi86.h>
180 #include <asm/sunddi.h>
183 #if (defined(__MACH__) && defined(__APPLE__))
187 /* Clarification about OUTB/OUTW/OUTL argument order:
188 * OUT[BWL](val, port)
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.
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); })
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
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)
226 #define OUTB(x,y) outportb(y, x)
227 #define OUTW(x,y) outportw(y, x)
228 #define OUTL(x,y) outportl(y, x)
235 /* This is the usual glibc interface. */
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
260 #elif defined (__OpenBSD__)
261 #if defined(__i386__)
262 #define iopl i386_iopl
263 #elif defined(__amd64__)
264 #define iopl amd64_iopl
268 static inline void outb(uint8_t value, uint16_t port)
270 asm volatile ("outb %b0,%w1": :"a" (value), "Nd" (port));
273 static inline uint8_t inb(uint16_t port)
276 asm volatile ("inb %w1,%0":"=a" (value):"Nd" (port));
280 static inline void outw(uint16_t value, uint16_t port)
282 asm volatile ("outw %w0,%w1": :"a" (value), "Nd" (port));
285 static inline uint16_t inw(uint16_t port)
288 asm volatile ("inw %w1,%0":"=a" (value):"Nd" (port));
292 static inline void outl(uint32_t value, uint16_t port)
294 asm volatile ("outl %0,%w1": :"a" (value), "Nd" (port));
297 static inline uint32_t inl(uint16_t port)
300 asm volatile ("inl %1,%0":"=a" (value):"Nd" (port));
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);
311 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
312 /* FreeBSD already has conflicting definitions for wrmsr/rdmsr. */
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);
321 #if defined(__LIBPAYLOAD__)
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);
328 #define rdmsr libpayload_rdmsr
329 #define wrmsr libpayload_wrmsr
332 #elif defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || defined(__ppc64__)
334 /* PCI port I/O is not yet implemented on PowerPC. */
336 #elif defined (__mips) || defined (__mips__) || defined (_mips) || defined (mips)
338 /* PCI port I/O is not yet implemented on MIPS. */
340 #elif defined(__arm__)
342 /* Non memory mapped I/O is not supported on ARM. */
346 #error Unknown architecture, please check if it supports PCI port IO.
351 #endif /* !__HWACCESS_H__ */