blob: a4fd50254eb4b6cce35f930accbd10d01d044a2b [file] [log] [blame]
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +00001/*
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
Uwe Hermann43959702010-03-13 17:28:29 +000018 */
19
20/*
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +000021 * Header file for hardware access and OS abstraction. Included from flash.h.
22 */
23
24#ifndef __HWACCESS_H__
25#define __HWACCESS_H__ 1
26
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000027#include "platform.h"
28
29#if IS_X86
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +000030#if defined(__GLIBC__)
31#include <sys/io.h>
32#endif
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000033#endif
34
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +000035#if NEED_PCI == 1
Carl-Daniel Hailfinger72376832010-06-25 13:18:48 +000036/*
37 * libpci headers use the variable name "index" which triggers shadowing
38 * warnings on systems which have the index() function in a default #include
39 * or as builtin.
40 */
41#define index shadow_workaround_index
Stefan Taunerc65b8552013-09-12 15:48:39 +000042
Stefan Tauner8d21ff12015-01-10 09:33:06 +000043#if !defined (__NetBSD__)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +000044#include <pci/pci.h>
Stefan Taunerc65b8552013-09-12 15:48:39 +000045#else
46#include <pciutils/pci.h>
47#endif
48
Carl-Daniel Hailfinger72376832010-06-25 13:18:48 +000049#undef index
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000050#endif /* NEED_PCI == 1 */
51
52
53/* The next big hunk tries to guess endianess from various preprocessor macros */
54/* First some error checking in case some weird header has defines both.
55 * NB: OpenBSD always defines _BIG_ENDIAN and _LITTLE_ENDIAN. */
56#if defined (__LITTLE_ENDIAN__) && defined (__BIG_ENDIAN__)
57#error Conflicting endianness #define
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +000058#endif
59
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000060#if IS_X86
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000061
62/* All x86 is little-endian. */
63#define __FLASHROM_LITTLE_ENDIAN__ 1
64
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000065#elif IS_MIPS
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000066
67/* MIPS can be either endian. */
68#if defined (__MIPSEL) || defined (__MIPSEL__) || defined (_MIPSEL) || defined (MIPSEL)
69#define __FLASHROM_LITTLE_ENDIAN__ 1
70#elif defined (__MIPSEB) || defined (__MIPSEB__) || defined (_MIPSEB) || defined (MIPSEB)
71#define __FLASHROM_BIG_ENDIAN__ 1
72#endif
73
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000074#elif IS_PPC
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000075
76/* PowerPC can be either endian. */
77#if defined (_BIG_ENDIAN) || defined (__BIG_ENDIAN__)
78#define __FLASHROM_BIG_ENDIAN__ 1
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000079#elif defined (_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__)
David Hendricksb286da72012-02-13 00:35:35 +000080#define __FLASHROM_LITTLE_ENDIAN__ 1
David Hendricksb286da72012-02-13 00:35:35 +000081#endif
82
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000083#elif IS_ARM
84
85/* ARM can be either endian. */
86#if defined (__ARMEB__)
87#define __FLASHROM_BIG_ENDIAN__ 1
88#elif defined (__ARMEL__)
89#define __FLASHROM_LITTLE_ENDIAN__ 1
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000090#endif
91
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000092#endif /* IS_? */
93
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000094#if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__)
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000095
96/* If architecture-specific approaches fail try generic variants. First: BSD (works about everywhere). */
97#if !IS_WINDOWS
98#include <sys/param.h>
99
100#if defined (__BYTE_ORDER)
101#if __BYTE_ORDER == __LITTLE_ENDIAN
102#define __FLASHROM_LITTLE_ENDIAN__
103#elif __BYTE_ORDER == __BIG_ENDIAN
104#define __FLASHROM_BIG_ENDIAN__
105#else
106#error Unknown byte order!
107#endif
108#endif /* defined __BYTE_ORDER */
109#endif /* !IS_WINDOWS */
110
111#if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__)
112
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000113/* Nonstandard libc-specific macros for determining endianness. */
114#if defined(__GLIBC__)
115#include <endian.h>
116#if BYTE_ORDER == LITTLE_ENDIAN
117#define __FLASHROM_LITTLE_ENDIAN__ 1
118#elif BYTE_ORDER == BIG_ENDIAN
119#define __FLASHROM_BIG_ENDIAN__ 1
120#endif
121#endif
122#endif
123
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000124#endif
125
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000126#if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__)
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000127#error Unable to determine endianness.
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000128#endif
129
130#define ___constant_swab8(x) ((uint8_t) ( \
131 (((uint8_t)(x) & (uint8_t)0xffU))))
132
133#define ___constant_swab16(x) ((uint16_t) ( \
134 (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
135 (((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
136
137#define ___constant_swab32(x) ((uint32_t) ( \
138 (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
139 (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
140 (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
141 (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
142
143#define ___constant_swab64(x) ((uint64_t) ( \
144 (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
145 (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
146 (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
147 (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
148 (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
149 (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
150 (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
151 (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56)))
152
153#if defined (__FLASHROM_BIG_ENDIAN__)
154
155#define cpu_to_le(bits) \
156static inline uint##bits##_t cpu_to_le##bits(uint##bits##_t val) \
157{ \
158 return ___constant_swab##bits(val); \
159}
160
161cpu_to_le(8)
162cpu_to_le(16)
163cpu_to_le(32)
164cpu_to_le(64)
165
166#define cpu_to_be8
167#define cpu_to_be16
168#define cpu_to_be32
169#define cpu_to_be64
170
171#elif defined (__FLASHROM_LITTLE_ENDIAN__)
172
173#define cpu_to_be(bits) \
174static inline uint##bits##_t cpu_to_be##bits(uint##bits##_t val) \
175{ \
176 return ___constant_swab##bits(val); \
177}
178
179cpu_to_be(8)
180cpu_to_be(16)
181cpu_to_be(32)
182cpu_to_be(64)
183
184#define cpu_to_le8
185#define cpu_to_le16
186#define cpu_to_le32
187#define cpu_to_le64
188
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000189#endif /* __FLASHROM_BIG_ENDIAN__ / __FLASHROM_LITTLE_ENDIAN__ */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000190
191#define be_to_cpu8 cpu_to_be8
192#define be_to_cpu16 cpu_to_be16
193#define be_to_cpu32 cpu_to_be32
194#define be_to_cpu64 cpu_to_be64
195#define le_to_cpu8 cpu_to_le8
196#define le_to_cpu16 cpu_to_le16
197#define le_to_cpu32 cpu_to_le32
198#define le_to_cpu64 cpu_to_le64
199
Carl-Daniel Hailfinger41bea032010-07-29 13:17:37 +0000200#if NEED_PCI == 1
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000201#if IS_X86
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000202
203#define __FLASHROM_HAVE_OUTB__ 1
204
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000205/* for iopl and outb under Solaris */
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000206#if defined (__sun)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000207#include <sys/sysi86.h>
208#include <sys/psw.h>
209#include <asm/sunddi.h>
210#endif
211
Carl-Daniel Hailfinger0d974e72010-07-17 12:54:09 +0000212/* Clarification about OUTB/OUTW/OUTL argument order:
213 * OUT[BWL](val, port)
214 */
215
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000216#if defined(__FreeBSD__) || defined(__DragonFly__)
Carl-Daniel Hailfingera5eecda2012-02-25 22:50:21 +0000217 /* Note that Debian/kFreeBSD (FreeBSD kernel with glibc) has conflicting
218 * out[bwl] definitions in machine/cpufunc.h and sys/io.h at least in some
219 * versions. Use machine/cpufunc.h only for plain FreeBSD/DragonFlyBSD.
220 */
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000221 #include <machine/cpufunc.h>
Michael Karchere7f32092010-01-12 15:36:24 +0000222 #define OUTB(x, y) do { u_int outb_tmp = (y); outb(outb_tmp, (x)); } while (0)
223 #define OUTW(x, y) do { u_int outw_tmp = (y); outw(outw_tmp, (x)); } while (0)
224 #define OUTL(x, y) do { u_int outl_tmp = (y); outl(outl_tmp, (x)); } while (0)
225 #define INB(x) __extension__ ({ u_int inb_tmp = (x); inb(inb_tmp); })
226 #define INW(x) __extension__ ({ u_int inw_tmp = (x); inw(inw_tmp); })
227 #define INL(x) __extension__ ({ u_int inl_tmp = (x); inl(inl_tmp); })
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000228#else
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000229
Carl-Daniel Hailfinger60d9bd22012-08-09 23:34:41 +0000230#if defined(__MACH__) && defined(__APPLE__)
Carl-Daniel Hailfingerf992c192010-10-06 23:16:10 +0000231 /* Header is part of the DirectHW library. */
Stefan Reinauer83704c52011-03-18 22:00:15 +0000232 #include <DirectHW/DirectHW.h>
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000233#else
234
235#if defined (__sun)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000236 /* Note different order for outb */
237 #define OUTB(x,y) outb(y, x)
238 #define OUTW(x,y) outw(y, x)
239 #define OUTL(x,y) outl(y, x)
240 #define INB inb
241 #define INW inw
242 #define INL inl
243#else
Rudolf Marek03ae5c12010-03-16 23:59:19 +0000244
245#ifdef __DJGPP__
246
247#include <pc.h>
248
249 #define OUTB(x,y) outportb(y, x)
250 #define OUTW(x,y) outportw(y, x)
251 #define OUTL(x,y) outportl(y, x)
252
253 #define INB inportb
254 #define INW inportw
255 #define INL inportl
256
Uwe Hermann91f4afa2011-07-28 08:13:25 +0000257#else
Carl-Daniel Hailfingera5eecda2012-02-25 22:50:21 +0000258 /* This is the usual glibc interface. */
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000259 #define OUTB outb
260 #define OUTW outw
261 #define OUTL outl
262 #define INB inb
263 #define INW inw
264 #define INL inl
Rudolf Marek03ae5c12010-03-16 23:59:19 +0000265#endif
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000266#endif
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000267#endif
268#endif
269
Carl-Daniel Hailfingerb63b0672010-07-02 17:12:50 +0000270#if defined(__NetBSD__) || defined (__OpenBSD__)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000271 #if defined(__i386__) || defined(__x86_64__)
272 #include <sys/types.h>
273 #include <machine/sysarch.h>
Stefan Tauner0554ca52013-07-25 22:54:25 +0000274 #if defined(__NetBSD__)
275 #if defined(__i386__)
276 #define iopl i386_iopl
277 #elif defined(__x86_64__)
278 #define iopl x86_64_iopl
279 #endif
280 #elif defined (__OpenBSD__)
281 #if defined(__i386__)
282 #define iopl i386_iopl
283 #elif defined(__amd64__)
284 #define iopl amd64_iopl
285 #endif
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000286 #endif
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000287
Uwe Hermann43959702010-03-13 17:28:29 +0000288static inline void outb(uint8_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000289{
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000290 __asm__ volatile ("outb %b0,%w1": :"a" (value), "Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000291}
292
Uwe Hermann43959702010-03-13 17:28:29 +0000293static inline uint8_t inb(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000294{
295 uint8_t value;
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000296 __asm__ volatile ("inb %w1,%0":"=a" (value):"Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000297 return value;
298}
299
Uwe Hermann43959702010-03-13 17:28:29 +0000300static inline void outw(uint16_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000301{
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000302 __asm__ volatile ("outw %w0,%w1": :"a" (value), "Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000303}
304
Uwe Hermann43959702010-03-13 17:28:29 +0000305static inline uint16_t inw(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000306{
307 uint16_t value;
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000308 __asm__ volatile ("inw %w1,%0":"=a" (value):"Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000309 return value;
310}
311
Uwe Hermann43959702010-03-13 17:28:29 +0000312static inline void outl(uint32_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000313{
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000314 __asm__ volatile ("outl %0,%w1": :"a" (value), "Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000315}
316
Uwe Hermann43959702010-03-13 17:28:29 +0000317static inline uint32_t inl(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000318{
319 uint32_t value;
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000320 __asm__ volatile ("inl %1,%0":"=a" (value):"Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000321 return value;
322}
323 #endif
324#endif
325
Carl-Daniel Hailfinger60d9bd22012-08-09 23:34:41 +0000326#if !(defined(__MACH__) && defined(__APPLE__)) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && !defined(__DragonFly__) && !defined(__LIBPAYLOAD__)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000327typedef struct { uint32_t hi, lo; } msr_t;
328msr_t rdmsr(int addr);
329int wrmsr(int addr, msr_t msr);
330#endif
Carl-Daniel Hailfingera5eecda2012-02-25 22:50:21 +0000331#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000332/* FreeBSD already has conflicting definitions for wrmsr/rdmsr. */
333#undef rdmsr
334#undef wrmsr
335#define rdmsr freebsd_rdmsr
336#define wrmsr freebsd_wrmsr
337typedef struct { uint32_t hi, lo; } msr_t;
338msr_t freebsd_rdmsr(int addr);
339int freebsd_wrmsr(int addr, msr_t msr);
340#endif
Patrick Georgia9095a92010-09-30 17:03:32 +0000341#if defined(__LIBPAYLOAD__)
342#include <arch/io.h>
343#include <arch/msr.h>
344typedef struct { uint32_t hi, lo; } msr_t;
345msr_t libpayload_rdmsr(int addr);
346int libpayload_wrmsr(int addr, msr_t msr);
347#undef rdmsr
348#define rdmsr libpayload_rdmsr
349#define wrmsr libpayload_wrmsr
350#endif
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000351
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000352#elif IS_PPC
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000353
354/* PCI port I/O is not yet implemented on PowerPC. */
355
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000356#elif IS_MIPS
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000357
358/* PCI port I/O is not yet implemented on MIPS. */
359
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000360#elif IS_ARM
David Hendricksb286da72012-02-13 00:35:35 +0000361
362/* Non memory mapped I/O is not supported on ARM. */
363
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000364#else
365
366#error Unknown architecture, please check if it supports PCI port IO.
367
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000368#endif /* IS_* */
369#endif /* NEED_PCI == 1 */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000370
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000371#endif /* !__HWACCESS_H__ */