blob: 537836101dccf7f5d28a4ae9499c1ba2ca59da55 [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 Taunerfb2d77c2015-02-10 08:03:10 +000092#elif IS_SPARC
93/* SPARC is big endian in general (but allows to access data in little endian too). */
94#define __FLASHROM_BIG_ENDIAN__ 1
95
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000096#endif /* IS_? */
97
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000098#if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__)
Stefan Taunerb0eee9b2015-01-10 09:32:50 +000099
100/* If architecture-specific approaches fail try generic variants. First: BSD (works about everywhere). */
101#if !IS_WINDOWS
102#include <sys/param.h>
103
104#if defined (__BYTE_ORDER)
105#if __BYTE_ORDER == __LITTLE_ENDIAN
106#define __FLASHROM_LITTLE_ENDIAN__
107#elif __BYTE_ORDER == __BIG_ENDIAN
108#define __FLASHROM_BIG_ENDIAN__
109#else
110#error Unknown byte order!
111#endif
112#endif /* defined __BYTE_ORDER */
113#endif /* !IS_WINDOWS */
114
115#if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__)
116
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000117/* Nonstandard libc-specific macros for determining endianness. */
118#if defined(__GLIBC__)
119#include <endian.h>
120#if BYTE_ORDER == LITTLE_ENDIAN
121#define __FLASHROM_LITTLE_ENDIAN__ 1
122#elif BYTE_ORDER == BIG_ENDIAN
123#define __FLASHROM_BIG_ENDIAN__ 1
124#endif
125#endif
126#endif
127
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000128#endif
129
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000130#if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__)
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000131#error Unable to determine endianness.
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000132#endif
133
134#define ___constant_swab8(x) ((uint8_t) ( \
135 (((uint8_t)(x) & (uint8_t)0xffU))))
136
137#define ___constant_swab16(x) ((uint16_t) ( \
138 (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
139 (((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
140
141#define ___constant_swab32(x) ((uint32_t) ( \
142 (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
143 (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
144 (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
145 (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
146
147#define ___constant_swab64(x) ((uint64_t) ( \
148 (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
149 (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
150 (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
151 (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
152 (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
153 (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
154 (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
155 (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56)))
156
157#if defined (__FLASHROM_BIG_ENDIAN__)
158
159#define cpu_to_le(bits) \
160static inline uint##bits##_t cpu_to_le##bits(uint##bits##_t val) \
161{ \
162 return ___constant_swab##bits(val); \
163}
164
165cpu_to_le(8)
166cpu_to_le(16)
167cpu_to_le(32)
168cpu_to_le(64)
169
170#define cpu_to_be8
171#define cpu_to_be16
172#define cpu_to_be32
173#define cpu_to_be64
174
175#elif defined (__FLASHROM_LITTLE_ENDIAN__)
176
177#define cpu_to_be(bits) \
178static inline uint##bits##_t cpu_to_be##bits(uint##bits##_t val) \
179{ \
180 return ___constant_swab##bits(val); \
181}
182
183cpu_to_be(8)
184cpu_to_be(16)
185cpu_to_be(32)
186cpu_to_be(64)
187
188#define cpu_to_le8
189#define cpu_to_le16
190#define cpu_to_le32
191#define cpu_to_le64
192
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000193#endif /* __FLASHROM_BIG_ENDIAN__ / __FLASHROM_LITTLE_ENDIAN__ */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000194
195#define be_to_cpu8 cpu_to_be8
196#define be_to_cpu16 cpu_to_be16
197#define be_to_cpu32 cpu_to_be32
198#define be_to_cpu64 cpu_to_be64
199#define le_to_cpu8 cpu_to_le8
200#define le_to_cpu16 cpu_to_le16
201#define le_to_cpu32 cpu_to_le32
202#define le_to_cpu64 cpu_to_le64
203
Carl-Daniel Hailfinger41bea032010-07-29 13:17:37 +0000204#if NEED_PCI == 1
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000205#if IS_X86
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000206
207#define __FLASHROM_HAVE_OUTB__ 1
208
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000209/* for iopl and outb under Solaris */
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000210#if defined (__sun)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000211#include <sys/sysi86.h>
212#include <sys/psw.h>
213#include <asm/sunddi.h>
214#endif
215
Carl-Daniel Hailfinger0d974e72010-07-17 12:54:09 +0000216/* Clarification about OUTB/OUTW/OUTL argument order:
217 * OUT[BWL](val, port)
218 */
219
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000220#if defined(__FreeBSD__) || defined(__DragonFly__)
Carl-Daniel Hailfingera5eecda2012-02-25 22:50:21 +0000221 /* Note that Debian/kFreeBSD (FreeBSD kernel with glibc) has conflicting
222 * out[bwl] definitions in machine/cpufunc.h and sys/io.h at least in some
223 * versions. Use machine/cpufunc.h only for plain FreeBSD/DragonFlyBSD.
224 */
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000225 #include <machine/cpufunc.h>
Michael Karchere7f32092010-01-12 15:36:24 +0000226 #define OUTB(x, y) do { u_int outb_tmp = (y); outb(outb_tmp, (x)); } while (0)
227 #define OUTW(x, y) do { u_int outw_tmp = (y); outw(outw_tmp, (x)); } while (0)
228 #define OUTL(x, y) do { u_int outl_tmp = (y); outl(outl_tmp, (x)); } while (0)
229 #define INB(x) __extension__ ({ u_int inb_tmp = (x); inb(inb_tmp); })
230 #define INW(x) __extension__ ({ u_int inw_tmp = (x); inw(inw_tmp); })
231 #define INL(x) __extension__ ({ u_int inl_tmp = (x); inl(inl_tmp); })
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000232#else
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000233
Carl-Daniel Hailfinger60d9bd22012-08-09 23:34:41 +0000234#if defined(__MACH__) && defined(__APPLE__)
Carl-Daniel Hailfingerf992c192010-10-06 23:16:10 +0000235 /* Header is part of the DirectHW library. */
Stefan Reinauer83704c52011-03-18 22:00:15 +0000236 #include <DirectHW/DirectHW.h>
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000237#else
238
239#if defined (__sun)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000240 /* Note different order for outb */
241 #define OUTB(x,y) outb(y, x)
242 #define OUTW(x,y) outw(y, x)
243 #define OUTL(x,y) outl(y, x)
244 #define INB inb
245 #define INW inw
246 #define INL inl
247#else
Rudolf Marek03ae5c12010-03-16 23:59:19 +0000248
249#ifdef __DJGPP__
250
251#include <pc.h>
252
253 #define OUTB(x,y) outportb(y, x)
254 #define OUTW(x,y) outportw(y, x)
255 #define OUTL(x,y) outportl(y, x)
256
257 #define INB inportb
258 #define INW inportw
259 #define INL inportl
260
Uwe Hermann91f4afa2011-07-28 08:13:25 +0000261#else
Carl-Daniel Hailfingera5eecda2012-02-25 22:50:21 +0000262 /* This is the usual glibc interface. */
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000263 #define OUTB outb
264 #define OUTW outw
265 #define OUTL outl
266 #define INB inb
267 #define INW inw
268 #define INL inl
Rudolf Marek03ae5c12010-03-16 23:59:19 +0000269#endif
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000270#endif
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000271#endif
272#endif
273
Carl-Daniel Hailfingerb63b0672010-07-02 17:12:50 +0000274#if defined(__NetBSD__) || defined (__OpenBSD__)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000275 #if defined(__i386__) || defined(__x86_64__)
276 #include <sys/types.h>
277 #include <machine/sysarch.h>
Stefan Tauner0554ca52013-07-25 22:54:25 +0000278 #if defined(__NetBSD__)
279 #if defined(__i386__)
280 #define iopl i386_iopl
281 #elif defined(__x86_64__)
282 #define iopl x86_64_iopl
283 #endif
284 #elif defined (__OpenBSD__)
285 #if defined(__i386__)
286 #define iopl i386_iopl
287 #elif defined(__amd64__)
288 #define iopl amd64_iopl
289 #endif
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000290 #endif
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000291
Uwe Hermann43959702010-03-13 17:28:29 +0000292static inline void outb(uint8_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000293{
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000294 __asm__ volatile ("outb %b0,%w1": :"a" (value), "Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000295}
296
Uwe Hermann43959702010-03-13 17:28:29 +0000297static inline uint8_t inb(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000298{
299 uint8_t value;
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000300 __asm__ volatile ("inb %w1,%0":"=a" (value):"Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000301 return value;
302}
303
Uwe Hermann43959702010-03-13 17:28:29 +0000304static inline void outw(uint16_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000305{
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000306 __asm__ volatile ("outw %w0,%w1": :"a" (value), "Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000307}
308
Uwe Hermann43959702010-03-13 17:28:29 +0000309static inline uint16_t inw(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000310{
311 uint16_t value;
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000312 __asm__ volatile ("inw %w1,%0":"=a" (value):"Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000313 return value;
314}
315
Uwe Hermann43959702010-03-13 17:28:29 +0000316static inline void outl(uint32_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000317{
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000318 __asm__ volatile ("outl %0,%w1": :"a" (value), "Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000319}
320
Uwe Hermann43959702010-03-13 17:28:29 +0000321static inline uint32_t inl(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000322{
323 uint32_t value;
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +0000324 __asm__ volatile ("inl %1,%0":"=a" (value):"Nd" (port));
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000325 return value;
326}
327 #endif
328#endif
329
Carl-Daniel Hailfinger60d9bd22012-08-09 23:34:41 +0000330#if !(defined(__MACH__) && defined(__APPLE__)) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && !defined(__DragonFly__) && !defined(__LIBPAYLOAD__)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000331typedef struct { uint32_t hi, lo; } msr_t;
332msr_t rdmsr(int addr);
333int wrmsr(int addr, msr_t msr);
334#endif
Carl-Daniel Hailfingera5eecda2012-02-25 22:50:21 +0000335#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000336/* FreeBSD already has conflicting definitions for wrmsr/rdmsr. */
337#undef rdmsr
338#undef wrmsr
339#define rdmsr freebsd_rdmsr
340#define wrmsr freebsd_wrmsr
341typedef struct { uint32_t hi, lo; } msr_t;
342msr_t freebsd_rdmsr(int addr);
343int freebsd_wrmsr(int addr, msr_t msr);
344#endif
Patrick Georgia9095a92010-09-30 17:03:32 +0000345#if defined(__LIBPAYLOAD__)
346#include <arch/io.h>
347#include <arch/msr.h>
348typedef struct { uint32_t hi, lo; } msr_t;
349msr_t libpayload_rdmsr(int addr);
350int libpayload_wrmsr(int addr, msr_t msr);
351#undef rdmsr
352#define rdmsr libpayload_rdmsr
353#define wrmsr libpayload_wrmsr
354#endif
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000355
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000356#elif IS_PPC
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000357
358/* PCI port I/O is not yet implemented on PowerPC. */
359
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000360#elif IS_MIPS
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000361
362/* PCI port I/O is not yet implemented on MIPS. */
363
Stefan Taunerfb2d77c2015-02-10 08:03:10 +0000364#elif IS_SPARC
365
366/* PCI port I/O is not yet implemented on SPARC. */
367
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000368#elif IS_ARM
David Hendricksb286da72012-02-13 00:35:35 +0000369
370/* Non memory mapped I/O is not supported on ARM. */
371
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000372#else
373
374#error Unknown architecture, please check if it supports PCI port IO.
375
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000376#endif /* IS_* */
377#endif /* NEED_PCI == 1 */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000378
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000379#endif /* !__HWACCESS_H__ */