blob: bc5cb9bda8c9f887ba0e588917f464a41b61ca34 [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
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000046#define ___constant_swab8(x) ((uint8_t) ( \
47 (((uint8_t)(x) & (uint8_t)0xffU))))
48
49#define ___constant_swab16(x) ((uint16_t) ( \
50 (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
51 (((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
52
53#define ___constant_swab32(x) ((uint32_t) ( \
54 (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
55 (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
56 (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
57 (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
58
59#define ___constant_swab64(x) ((uint64_t) ( \
60 (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
61 (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
62 (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
63 (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
64 (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
65 (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
66 (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
67 (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56)))
68
69#if defined (__FLASHROM_BIG_ENDIAN__)
70
71#define cpu_to_le(bits) \
72static inline uint##bits##_t cpu_to_le##bits(uint##bits##_t val) \
73{ \
74 return ___constant_swab##bits(val); \
75}
76
77cpu_to_le(8)
78cpu_to_le(16)
79cpu_to_le(32)
80cpu_to_le(64)
81
82#define cpu_to_be8
83#define cpu_to_be16
84#define cpu_to_be32
85#define cpu_to_be64
86
87#elif defined (__FLASHROM_LITTLE_ENDIAN__)
88
89#define cpu_to_be(bits) \
90static inline uint##bits##_t cpu_to_be##bits(uint##bits##_t val) \
91{ \
92 return ___constant_swab##bits(val); \
93}
94
95cpu_to_be(8)
96cpu_to_be(16)
97cpu_to_be(32)
98cpu_to_be(64)
99
100#define cpu_to_le8
101#define cpu_to_le16
102#define cpu_to_le32
103#define cpu_to_le64
104
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000105#endif /* __FLASHROM_BIG_ENDIAN__ / __FLASHROM_LITTLE_ENDIAN__ */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000106
107#define be_to_cpu8 cpu_to_be8
108#define be_to_cpu16 cpu_to_be16
109#define be_to_cpu32 cpu_to_be32
110#define be_to_cpu64 cpu_to_be64
111#define le_to_cpu8 cpu_to_le8
112#define le_to_cpu16 cpu_to_le16
113#define le_to_cpu32 cpu_to_le32
114#define le_to_cpu64 cpu_to_le64
115
Carl-Daniel Hailfinger16c0aec2016-02-20 21:43:56 +0000116#if NEED_RAW_ACCESS == 1
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000117#if IS_X86
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000118
Gwenhael Goavec-Merou8cd0c732015-11-14 02:55:12 +0000119/* sys/io.h provides iopl(2) and x86 I/O port access functions (inb, outb etc).
120 * It is included in glibc (thus available also on debian/kFreeBSD) but also in other libcs that mimic glibc,
Stefan Tauner2c57bbe2016-02-20 20:21:58 +0000121 * e.g. musl and uclibc. Because we cannot detect the libc or existence of the header or of the instructions
122 * themselves safely in here we use some heuristic below:
123 * On Android we don't have the header file and no way for I/O port access at all. However, sys/glibc-syscalls.h
124 * refers to an iopl implementation and we therefore include at least that one for now. On non-Android we assume
125 * that a Linux system's libc has a suitable sys/io.h or (on non-Linux) we depend on glibc to offer it. */
126#if defined(__ANDROID__)
127#include <sys/glibc-syscalls.h>
128#elif defined(__linux__) || defined(__GLIBC__)
Gwenhael Goavec-Merou8cd0c732015-11-14 02:55:12 +0000129#include <sys/io.h>
130#endif
131
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000132#define __FLASHROM_HAVE_OUTB__ 1
133
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000134/* for iopl and outb under Solaris */
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000135#if defined (__sun)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000136#include <sys/sysi86.h>
137#include <sys/psw.h>
138#include <asm/sunddi.h>
139#endif
140
Carl-Daniel Hailfinger0d974e72010-07-17 12:54:09 +0000141/* Clarification about OUTB/OUTW/OUTL argument order:
142 * OUT[BWL](val, port)
143 */
144
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000145#if defined(__FreeBSD__) || defined(__DragonFly__)
Carl-Daniel Hailfingera5eecda2012-02-25 22:50:21 +0000146 /* Note that Debian/kFreeBSD (FreeBSD kernel with glibc) has conflicting
147 * out[bwl] definitions in machine/cpufunc.h and sys/io.h at least in some
148 * versions. Use machine/cpufunc.h only for plain FreeBSD/DragonFlyBSD.
149 */
Carl-Daniel Hailfinger16c0aec2016-02-20 21:43:56 +0000150 #include <sys/types.h>
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000151 #include <machine/cpufunc.h>
Michael Karchere7f32092010-01-12 15:36:24 +0000152 #define OUTB(x, y) do { u_int outb_tmp = (y); outb(outb_tmp, (x)); } while (0)
153 #define OUTW(x, y) do { u_int outw_tmp = (y); outw(outw_tmp, (x)); } while (0)
154 #define OUTL(x, y) do { u_int outl_tmp = (y); outl(outl_tmp, (x)); } while (0)
155 #define INB(x) __extension__ ({ u_int inb_tmp = (x); inb(inb_tmp); })
156 #define INW(x) __extension__ ({ u_int inw_tmp = (x); inw(inw_tmp); })
157 #define INL(x) __extension__ ({ u_int inl_tmp = (x); inl(inl_tmp); })
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000158#else
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000159
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000160#if defined (__sun)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000161 /* Note different order for outb */
162 #define OUTB(x,y) outb(y, x)
163 #define OUTW(x,y) outw(y, x)
164 #define OUTL(x,y) outl(y, x)
165 #define INB inb
166 #define INW inw
167 #define INL inl
168#else
Rudolf Marek03ae5c12010-03-16 23:59:19 +0000169
170#ifdef __DJGPP__
171
172#include <pc.h>
173
174 #define OUTB(x,y) outportb(y, x)
175 #define OUTW(x,y) outportw(y, x)
176 #define OUTL(x,y) outportl(y, x)
177
178 #define INB inportb
179 #define INW inportw
180 #define INL inportl
181
Uwe Hermann91f4afa2011-07-28 08:13:25 +0000182#else
Stefan Taunerc71759d2015-05-23 23:59:23 +0000183
184#if defined(__MACH__) && defined(__APPLE__)
185 /* Header is part of the DirectHW library. */
186 #include <DirectHW/DirectHW.h>
187#endif
188
Carl-Daniel Hailfingera5eecda2012-02-25 22:50:21 +0000189 /* This is the usual glibc interface. */
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000190 #define OUTB outb
191 #define OUTW outw
192 #define OUTL outl
193 #define INB inb
194 #define INW inw
195 #define INL inl
Rudolf Marek03ae5c12010-03-16 23:59:19 +0000196#endif
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000197#endif
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000198#endif
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000199
Carl-Daniel Hailfingerb63b0672010-07-02 17:12:50 +0000200#if defined(__NetBSD__) || defined (__OpenBSD__)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000201 #if defined(__i386__) || defined(__x86_64__)
202 #include <sys/types.h>
203 #include <machine/sysarch.h>
Stefan Tauner0554ca52013-07-25 22:54:25 +0000204 #if defined(__NetBSD__)
205 #if defined(__i386__)
206 #define iopl i386_iopl
207 #elif defined(__x86_64__)
208 #define iopl x86_64_iopl
209 #endif
210 #elif defined (__OpenBSD__)
211 #if defined(__i386__)
212 #define iopl i386_iopl
213 #elif defined(__amd64__)
214 #define iopl amd64_iopl
215 #endif
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000216 #endif
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000217
Uwe Hermann43959702010-03-13 17:28:29 +0000218static inline void outb(uint8_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000219{
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000220 __asm__ volatile ("outb %b0,%w1": :"a" (value), "Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000221}
222
Uwe Hermann43959702010-03-13 17:28:29 +0000223static inline uint8_t inb(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000224{
225 uint8_t value;
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000226 __asm__ volatile ("inb %w1,%0":"=a" (value):"Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000227 return value;
228}
229
Uwe Hermann43959702010-03-13 17:28:29 +0000230static inline void outw(uint16_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000231{
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000232 __asm__ volatile ("outw %w0,%w1": :"a" (value), "Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000233}
234
Uwe Hermann43959702010-03-13 17:28:29 +0000235static inline uint16_t inw(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000236{
237 uint16_t value;
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000238 __asm__ volatile ("inw %w1,%0":"=a" (value):"Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000239 return value;
240}
241
Uwe Hermann43959702010-03-13 17:28:29 +0000242static inline void outl(uint32_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000243{
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000244 __asm__ volatile ("outl %0,%w1": :"a" (value), "Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000245}
246
Uwe Hermann43959702010-03-13 17:28:29 +0000247static inline uint32_t inl(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000248{
249 uint32_t value;
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000250 __asm__ volatile ("inl %1,%0":"=a" (value):"Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000251 return value;
252}
253 #endif
254#endif
255
Carl-Daniel Hailfinger60d9bd22012-08-09 23:34:41 +0000256#if !(defined(__MACH__) && defined(__APPLE__)) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && !defined(__DragonFly__) && !defined(__LIBPAYLOAD__)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000257typedef struct { uint32_t hi, lo; } msr_t;
258msr_t rdmsr(int addr);
259int wrmsr(int addr, msr_t msr);
260#endif
Carl-Daniel Hailfingera5eecda2012-02-25 22:50:21 +0000261#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000262/* FreeBSD already has conflicting definitions for wrmsr/rdmsr. */
263#undef rdmsr
264#undef wrmsr
265#define rdmsr freebsd_rdmsr
266#define wrmsr freebsd_wrmsr
267typedef struct { uint32_t hi, lo; } msr_t;
268msr_t freebsd_rdmsr(int addr);
269int freebsd_wrmsr(int addr, msr_t msr);
270#endif
Patrick Georgia9095a92010-09-30 17:03:32 +0000271#if defined(__LIBPAYLOAD__)
272#include <arch/io.h>
273#include <arch/msr.h>
274typedef struct { uint32_t hi, lo; } msr_t;
275msr_t libpayload_rdmsr(int addr);
276int libpayload_wrmsr(int addr, msr_t msr);
277#undef rdmsr
278#define rdmsr libpayload_rdmsr
279#define wrmsr libpayload_wrmsr
280#endif
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000281
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000282#elif IS_PPC
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000283
284/* PCI port I/O is not yet implemented on PowerPC. */
285
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000286#elif IS_MIPS
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000287
288/* PCI port I/O is not yet implemented on MIPS. */
289
Stefan Taunerfb2d77c2015-02-10 08:03:10 +0000290#elif IS_SPARC
291
292/* PCI port I/O is not yet implemented on SPARC. */
293
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000294#elif IS_ARM
David Hendricksb286da72012-02-13 00:35:35 +0000295
296/* Non memory mapped I/O is not supported on ARM. */
297
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000298#else
299
300#error Unknown architecture, please check if it supports PCI port IO.
301
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000302#endif /* IS_* */
Carl-Daniel Hailfinger16c0aec2016-02-20 21:43:56 +0000303#endif /* NEED_RAW_ACCESS == 1 */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000304
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000305#endif /* !__HWACCESS_H__ */