blob: 390f0e44868d172326a0559cd590236d4df2b63c [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
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +000029#if NEED_PCI == 1
Carl-Daniel Hailfinger72376832010-06-25 13:18:48 +000030/*
31 * libpci headers use the variable name "index" which triggers shadowing
32 * warnings on systems which have the index() function in a default #include
33 * or as builtin.
34 */
35#define index shadow_workaround_index
Stefan Taunerc65b8552013-09-12 15:48:39 +000036
Stefan Tauner8d21ff12015-01-10 09:33:06 +000037#if !defined (__NetBSD__)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +000038#include <pci/pci.h>
Stefan Taunerc65b8552013-09-12 15:48:39 +000039#else
40#include <pciutils/pci.h>
41#endif
42
Carl-Daniel Hailfinger72376832010-06-25 13:18:48 +000043#undef index
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000044#endif /* NEED_PCI == 1 */
45
46
47/* The next big hunk tries to guess endianess from various preprocessor macros */
48/* First some error checking in case some weird header has defines both.
49 * NB: OpenBSD always defines _BIG_ENDIAN and _LITTLE_ENDIAN. */
50#if defined (__LITTLE_ENDIAN__) && defined (__BIG_ENDIAN__)
51#error Conflicting endianness #define
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +000052#endif
53
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000054#if IS_X86
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000055
56/* All x86 is little-endian. */
57#define __FLASHROM_LITTLE_ENDIAN__ 1
58
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000059#elif IS_MIPS
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000060
61/* MIPS can be either endian. */
62#if defined (__MIPSEL) || defined (__MIPSEL__) || defined (_MIPSEL) || defined (MIPSEL)
63#define __FLASHROM_LITTLE_ENDIAN__ 1
64#elif defined (__MIPSEB) || defined (__MIPSEB__) || defined (_MIPSEB) || defined (MIPSEB)
65#define __FLASHROM_BIG_ENDIAN__ 1
66#endif
67
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000068#elif IS_PPC
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000069
70/* PowerPC can be either endian. */
71#if defined (_BIG_ENDIAN) || defined (__BIG_ENDIAN__)
72#define __FLASHROM_BIG_ENDIAN__ 1
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000073#elif defined (_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__)
David Hendricksb286da72012-02-13 00:35:35 +000074#define __FLASHROM_LITTLE_ENDIAN__ 1
David Hendricksb286da72012-02-13 00:35:35 +000075#endif
76
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000077#elif IS_ARM
78
79/* ARM can be either endian. */
80#if defined (__ARMEB__)
81#define __FLASHROM_BIG_ENDIAN__ 1
82#elif defined (__ARMEL__)
83#define __FLASHROM_LITTLE_ENDIAN__ 1
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000084#endif
85
Stefan Taunerfb2d77c2015-02-10 08:03:10 +000086#elif IS_SPARC
87/* SPARC is big endian in general (but allows to access data in little endian too). */
88#define __FLASHROM_BIG_ENDIAN__ 1
89
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000090#endif /* IS_? */
91
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000092#if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__)
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000093
94/* If architecture-specific approaches fail try generic variants. First: BSD (works about everywhere). */
95#if !IS_WINDOWS
96#include <sys/param.h>
97
98#if defined (__BYTE_ORDER)
99#if __BYTE_ORDER == __LITTLE_ENDIAN
100#define __FLASHROM_LITTLE_ENDIAN__
101#elif __BYTE_ORDER == __BIG_ENDIAN
102#define __FLASHROM_BIG_ENDIAN__
103#else
104#error Unknown byte order!
105#endif
106#endif /* defined __BYTE_ORDER */
107#endif /* !IS_WINDOWS */
108
109#if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__)
110
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000111/* Nonstandard libc-specific macros for determining endianness. */
Gwenhael Goavec-Merou8cd0c732015-11-14 02:55:12 +0000112/* musl provides an endian.h as well... but it can not be detected from within C. */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000113#if defined(__GLIBC__)
114#include <endian.h>
115#if BYTE_ORDER == LITTLE_ENDIAN
116#define __FLASHROM_LITTLE_ENDIAN__ 1
117#elif BYTE_ORDER == BIG_ENDIAN
118#define __FLASHROM_BIG_ENDIAN__ 1
119#endif
120#endif
121#endif
122
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000123#endif
124
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000125#if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__)
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000126#error Unable to determine endianness.
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000127#endif
128
129#define ___constant_swab8(x) ((uint8_t) ( \
130 (((uint8_t)(x) & (uint8_t)0xffU))))
131
132#define ___constant_swab16(x) ((uint16_t) ( \
133 (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
134 (((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
135
136#define ___constant_swab32(x) ((uint32_t) ( \
137 (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
138 (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
139 (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
140 (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
141
142#define ___constant_swab64(x) ((uint64_t) ( \
143 (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
144 (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
145 (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
146 (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
147 (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
148 (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
149 (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
150 (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56)))
151
152#if defined (__FLASHROM_BIG_ENDIAN__)
153
154#define cpu_to_le(bits) \
155static inline uint##bits##_t cpu_to_le##bits(uint##bits##_t val) \
156{ \
157 return ___constant_swab##bits(val); \
158}
159
160cpu_to_le(8)
161cpu_to_le(16)
162cpu_to_le(32)
163cpu_to_le(64)
164
165#define cpu_to_be8
166#define cpu_to_be16
167#define cpu_to_be32
168#define cpu_to_be64
169
170#elif defined (__FLASHROM_LITTLE_ENDIAN__)
171
172#define cpu_to_be(bits) \
173static inline uint##bits##_t cpu_to_be##bits(uint##bits##_t val) \
174{ \
175 return ___constant_swab##bits(val); \
176}
177
178cpu_to_be(8)
179cpu_to_be(16)
180cpu_to_be(32)
181cpu_to_be(64)
182
183#define cpu_to_le8
184#define cpu_to_le16
185#define cpu_to_le32
186#define cpu_to_le64
187
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000188#endif /* __FLASHROM_BIG_ENDIAN__ / __FLASHROM_LITTLE_ENDIAN__ */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000189
190#define be_to_cpu8 cpu_to_be8
191#define be_to_cpu16 cpu_to_be16
192#define be_to_cpu32 cpu_to_be32
193#define be_to_cpu64 cpu_to_be64
194#define le_to_cpu8 cpu_to_le8
195#define le_to_cpu16 cpu_to_le16
196#define le_to_cpu32 cpu_to_le32
197#define le_to_cpu64 cpu_to_le64
198
Carl-Daniel Hailfinger41bea032010-07-29 13:17:37 +0000199#if NEED_PCI == 1
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000200#if IS_X86
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000201
Gwenhael Goavec-Merou8cd0c732015-11-14 02:55:12 +0000202/* sys/io.h provides iopl(2) and x86 I/O port access functions (inb, outb etc).
203 * It is included in glibc (thus available also on debian/kFreeBSD) but also in other libcs that mimic glibc,
204 * e.g. musl and uclibc. */
205#if defined(__linux__) || defined(__GLIBC__)
206#include <sys/io.h>
207#endif
208
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000209#define __FLASHROM_HAVE_OUTB__ 1
210
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000211/* for iopl and outb under Solaris */
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000212#if defined (__sun)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000213#include <sys/sysi86.h>
214#include <sys/psw.h>
215#include <asm/sunddi.h>
216#endif
217
Carl-Daniel Hailfinger0d974e72010-07-17 12:54:09 +0000218/* Clarification about OUTB/OUTW/OUTL argument order:
219 * OUT[BWL](val, port)
220 */
221
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000222#if defined(__FreeBSD__) || defined(__DragonFly__)
Carl-Daniel Hailfingera5eecda2012-02-25 22:50:21 +0000223 /* Note that Debian/kFreeBSD (FreeBSD kernel with glibc) has conflicting
224 * out[bwl] definitions in machine/cpufunc.h and sys/io.h at least in some
225 * versions. Use machine/cpufunc.h only for plain FreeBSD/DragonFlyBSD.
226 */
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000227 #include <machine/cpufunc.h>
Michael Karchere7f32092010-01-12 15:36:24 +0000228 #define OUTB(x, y) do { u_int outb_tmp = (y); outb(outb_tmp, (x)); } while (0)
229 #define OUTW(x, y) do { u_int outw_tmp = (y); outw(outw_tmp, (x)); } while (0)
230 #define OUTL(x, y) do { u_int outl_tmp = (y); outl(outl_tmp, (x)); } while (0)
231 #define INB(x) __extension__ ({ u_int inb_tmp = (x); inb(inb_tmp); })
232 #define INW(x) __extension__ ({ u_int inw_tmp = (x); inw(inw_tmp); })
233 #define INL(x) __extension__ ({ u_int inl_tmp = (x); inl(inl_tmp); })
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000234#else
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000235
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000236#if defined (__sun)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000237 /* Note different order for outb */
238 #define OUTB(x,y) outb(y, x)
239 #define OUTW(x,y) outw(y, x)
240 #define OUTL(x,y) outl(y, x)
241 #define INB inb
242 #define INW inw
243 #define INL inl
244#else
Rudolf Marek03ae5c12010-03-16 23:59:19 +0000245
246#ifdef __DJGPP__
247
248#include <pc.h>
249
250 #define OUTB(x,y) outportb(y, x)
251 #define OUTW(x,y) outportw(y, x)
252 #define OUTL(x,y) outportl(y, x)
253
254 #define INB inportb
255 #define INW inportw
256 #define INL inportl
257
Uwe Hermann91f4afa2011-07-28 08:13:25 +0000258#else
Stefan Taunerc71759d2015-05-23 23:59:23 +0000259
260#if defined(__MACH__) && defined(__APPLE__)
261 /* Header is part of the DirectHW library. */
262 #include <DirectHW/DirectHW.h>
263#endif
264
Carl-Daniel Hailfingera5eecda2012-02-25 22:50:21 +0000265 /* This is the usual glibc interface. */
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000266 #define OUTB outb
267 #define OUTW outw
268 #define OUTL outl
269 #define INB inb
270 #define INW inw
271 #define INL inl
Rudolf Marek03ae5c12010-03-16 23:59:19 +0000272#endif
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000273#endif
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000274#endif
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000275
Carl-Daniel Hailfingerb63b0672010-07-02 17:12:50 +0000276#if defined(__NetBSD__) || defined (__OpenBSD__)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000277 #if defined(__i386__) || defined(__x86_64__)
278 #include <sys/types.h>
279 #include <machine/sysarch.h>
Stefan Tauner0554ca52013-07-25 22:54:25 +0000280 #if defined(__NetBSD__)
281 #if defined(__i386__)
282 #define iopl i386_iopl
283 #elif defined(__x86_64__)
284 #define iopl x86_64_iopl
285 #endif
286 #elif defined (__OpenBSD__)
287 #if defined(__i386__)
288 #define iopl i386_iopl
289 #elif defined(__amd64__)
290 #define iopl amd64_iopl
291 #endif
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000292 #endif
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000293
Uwe Hermann43959702010-03-13 17:28:29 +0000294static inline void outb(uint8_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000295{
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000296 __asm__ volatile ("outb %b0,%w1": :"a" (value), "Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000297}
298
Uwe Hermann43959702010-03-13 17:28:29 +0000299static inline uint8_t inb(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000300{
301 uint8_t value;
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000302 __asm__ volatile ("inb %w1,%0":"=a" (value):"Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000303 return value;
304}
305
Uwe Hermann43959702010-03-13 17:28:29 +0000306static inline void outw(uint16_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000307{
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000308 __asm__ volatile ("outw %w0,%w1": :"a" (value), "Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000309}
310
Uwe Hermann43959702010-03-13 17:28:29 +0000311static inline uint16_t inw(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000312{
313 uint16_t value;
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000314 __asm__ volatile ("inw %w1,%0":"=a" (value):"Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000315 return value;
316}
317
Uwe Hermann43959702010-03-13 17:28:29 +0000318static inline void outl(uint32_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000319{
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000320 __asm__ volatile ("outl %0,%w1": :"a" (value), "Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000321}
322
Uwe Hermann43959702010-03-13 17:28:29 +0000323static inline uint32_t inl(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000324{
325 uint32_t value;
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000326 __asm__ volatile ("inl %1,%0":"=a" (value):"Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000327 return value;
328}
329 #endif
330#endif
331
Carl-Daniel Hailfinger60d9bd22012-08-09 23:34:41 +0000332#if !(defined(__MACH__) && defined(__APPLE__)) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && !defined(__DragonFly__) && !defined(__LIBPAYLOAD__)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000333typedef struct { uint32_t hi, lo; } msr_t;
334msr_t rdmsr(int addr);
335int wrmsr(int addr, msr_t msr);
336#endif
Carl-Daniel Hailfingera5eecda2012-02-25 22:50:21 +0000337#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000338/* FreeBSD already has conflicting definitions for wrmsr/rdmsr. */
339#undef rdmsr
340#undef wrmsr
341#define rdmsr freebsd_rdmsr
342#define wrmsr freebsd_wrmsr
343typedef struct { uint32_t hi, lo; } msr_t;
344msr_t freebsd_rdmsr(int addr);
345int freebsd_wrmsr(int addr, msr_t msr);
346#endif
Patrick Georgia9095a92010-09-30 17:03:32 +0000347#if defined(__LIBPAYLOAD__)
348#include <arch/io.h>
349#include <arch/msr.h>
350typedef struct { uint32_t hi, lo; } msr_t;
351msr_t libpayload_rdmsr(int addr);
352int libpayload_wrmsr(int addr, msr_t msr);
353#undef rdmsr
354#define rdmsr libpayload_rdmsr
355#define wrmsr libpayload_wrmsr
356#endif
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000357
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000358#elif IS_PPC
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000359
360/* PCI port I/O is not yet implemented on PowerPC. */
361
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000362#elif IS_MIPS
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000363
364/* PCI port I/O is not yet implemented on MIPS. */
365
Stefan Taunerfb2d77c2015-02-10 08:03:10 +0000366#elif IS_SPARC
367
368/* PCI port I/O is not yet implemented on SPARC. */
369
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000370#elif IS_ARM
David Hendricksb286da72012-02-13 00:35:35 +0000371
372/* Non memory mapped I/O is not supported on ARM. */
373
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000374#else
375
376#error Unknown architecture, please check if it supports PCI port IO.
377
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000378#endif /* IS_* */
379#endif /* NEED_PCI == 1 */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000380
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000381#endif /* !__HWACCESS_H__ */