blob: 91366a6626f902095bb760c64a0135c0ae529f7a [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
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000027#if defined (__i386__) || defined (__x86_64__)
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +000028#if defined(__GLIBC__)
29#include <sys/io.h>
30#endif
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000031#endif
32
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +000033#if NEED_PCI == 1
34#include <pci/pci.h>
35#endif
36
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000037#if defined (__i386__) || defined (__x86_64__)
38
39/* All x86 is little-endian. */
40#define __FLASHROM_LITTLE_ENDIAN__ 1
41
42#elif defined (__mips) || defined (__mips__) || defined (_mips) || defined (mips)
43
44/* MIPS can be either endian. */
45#if defined (__MIPSEL) || defined (__MIPSEL__) || defined (_MIPSEL) || defined (MIPSEL)
46#define __FLASHROM_LITTLE_ENDIAN__ 1
47#elif defined (__MIPSEB) || defined (__MIPSEB__) || defined (_MIPSEB) || defined (MIPSEB)
48#define __FLASHROM_BIG_ENDIAN__ 1
49#endif
50
51#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || defined(__ppc64__)
52
53/* PowerPC can be either endian. */
54#if defined (_BIG_ENDIAN) || defined (__BIG_ENDIAN__)
55#define __FLASHROM_BIG_ENDIAN__ 1
56/* Error checking in case some weird header has #defines for LE as well. */
57#if defined (_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__)
58#error Conflicting endianness #define
59#endif
60#else
61#error Little-endian PowerPC #defines are unknown
62#endif
63
64#endif
65
66#if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__)
67/* Nonstandard libc-specific macros for determining endianness. */
68#if defined(__GLIBC__)
69#include <endian.h>
70#if BYTE_ORDER == LITTLE_ENDIAN
71#define __FLASHROM_LITTLE_ENDIAN__ 1
72#elif BYTE_ORDER == BIG_ENDIAN
73#define __FLASHROM_BIG_ENDIAN__ 1
74#endif
75#endif
76#endif
77
78#if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__)
79#error Unable to determine endianness. Please add support for your arch or libc.
80#endif
81
82#define ___constant_swab8(x) ((uint8_t) ( \
83 (((uint8_t)(x) & (uint8_t)0xffU))))
84
85#define ___constant_swab16(x) ((uint16_t) ( \
86 (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \
87 (((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
88
89#define ___constant_swab32(x) ((uint32_t) ( \
90 (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
91 (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
92 (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
93 (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
94
95#define ___constant_swab64(x) ((uint64_t) ( \
96 (((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
97 (((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
98 (((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
99 (((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
100 (((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
101 (((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
102 (((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
103 (((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56)))
104
105#if defined (__FLASHROM_BIG_ENDIAN__)
106
107#define cpu_to_le(bits) \
108static inline uint##bits##_t cpu_to_le##bits(uint##bits##_t val) \
109{ \
110 return ___constant_swab##bits(val); \
111}
112
113cpu_to_le(8)
114cpu_to_le(16)
115cpu_to_le(32)
116cpu_to_le(64)
117
118#define cpu_to_be8
119#define cpu_to_be16
120#define cpu_to_be32
121#define cpu_to_be64
122
123#elif defined (__FLASHROM_LITTLE_ENDIAN__)
124
125#define cpu_to_be(bits) \
126static inline uint##bits##_t cpu_to_be##bits(uint##bits##_t val) \
127{ \
128 return ___constant_swab##bits(val); \
129}
130
131cpu_to_be(8)
132cpu_to_be(16)
133cpu_to_be(32)
134cpu_to_be(64)
135
136#define cpu_to_le8
137#define cpu_to_le16
138#define cpu_to_le32
139#define cpu_to_le64
140
141#else
142
143#error Could not determine endianness.
144
145#endif
146
147#define be_to_cpu8 cpu_to_be8
148#define be_to_cpu16 cpu_to_be16
149#define be_to_cpu32 cpu_to_be32
150#define be_to_cpu64 cpu_to_be64
151#define le_to_cpu8 cpu_to_le8
152#define le_to_cpu16 cpu_to_le16
153#define le_to_cpu32 cpu_to_le32
154#define le_to_cpu64 cpu_to_le64
155
156#if defined (__i386__) || defined (__x86_64__)
157
158#define __FLASHROM_HAVE_OUTB__ 1
159
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000160/* for iopl and outb under Solaris */
161#if defined (__sun) && (defined(__i386) || defined(__amd64))
162#include <strings.h>
163#include <sys/sysi86.h>
164#include <sys/psw.h>
165#include <asm/sunddi.h>
166#endif
167
168#if (defined(__MACH__) && defined(__APPLE__))
169#define __DARWIN__
170#endif
171
172#if defined(__FreeBSD__) || defined(__DragonFly__)
173 #include <machine/cpufunc.h>
174 #define off64_t off_t
175 #define lseek64 lseek
Michael Karchere7f32092010-01-12 15:36:24 +0000176 #define OUTB(x, y) do { u_int outb_tmp = (y); outb(outb_tmp, (x)); } while (0)
177 #define OUTW(x, y) do { u_int outw_tmp = (y); outw(outw_tmp, (x)); } while (0)
178 #define OUTL(x, y) do { u_int outl_tmp = (y); outl(outl_tmp, (x)); } while (0)
179 #define INB(x) __extension__ ({ u_int inb_tmp = (x); inb(inb_tmp); })
180 #define INW(x) __extension__ ({ u_int inw_tmp = (x); inw(inw_tmp); })
181 #define INL(x) __extension__ ({ u_int inl_tmp = (x); inl(inl_tmp); })
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000182#else
183#if defined(__DARWIN__)
184 #include <DirectIO/darwinio.h>
185 #define off64_t off_t
186 #define lseek64 lseek
187#endif
188#if defined (__sun) && (defined(__i386) || defined(__amd64))
189 /* Note different order for outb */
190 #define OUTB(x,y) outb(y, x)
191 #define OUTW(x,y) outw(y, x)
192 #define OUTL(x,y) outl(y, x)
193 #define INB inb
194 #define INW inw
195 #define INL inl
196#else
Rudolf Marek03ae5c12010-03-16 23:59:19 +0000197
198#ifdef __DJGPP__
199
200#include <pc.h>
201
202 #define OUTB(x,y) outportb(y, x)
203 #define OUTW(x,y) outportw(y, x)
204 #define OUTL(x,y) outportl(y, x)
205
206 #define INB inportb
207 #define INW inportw
208 #define INL inportl
209
210#else
211
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000212 #define OUTB outb
213 #define OUTW outw
214 #define OUTL outl
215 #define INB inb
216 #define INW inw
217 #define INL inl
Rudolf Marek03ae5c12010-03-16 23:59:19 +0000218
219#endif
220
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000221#endif
222#endif
223
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000224#if defined(__NetBSD__)
225 #define off64_t off_t
226 #define lseek64 lseek
227 #if defined(__i386__) || defined(__x86_64__)
228 #include <sys/types.h>
229 #include <machine/sysarch.h>
230 #if defined(__i386__)
231 #define iopl i386_iopl
232 #elif defined(__x86_64__)
233 #define iopl x86_64_iopl
234 #endif
235 #include <stdint.h>
236
Uwe Hermann43959702010-03-13 17:28:29 +0000237static inline void outb(uint8_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000238{
239 asm volatile ("outb %b0,%w1": :"a" (value), "Nd" (port));
240}
241
Uwe Hermann43959702010-03-13 17:28:29 +0000242static inline uint8_t inb(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000243{
244 uint8_t value;
245 asm volatile ("inb %w1,%0":"=a" (value):"Nd" (port));
246 return value;
247}
248
Uwe Hermann43959702010-03-13 17:28:29 +0000249static inline void outw(uint16_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000250{
251 asm volatile ("outw %w0,%w1": :"a" (value), "Nd" (port));
252}
253
Uwe Hermann43959702010-03-13 17:28:29 +0000254static inline uint16_t inw(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000255{
256 uint16_t value;
257 asm volatile ("inw %w1,%0":"=a" (value):"Nd" (port));
258 return value;
259}
260
Uwe Hermann43959702010-03-13 17:28:29 +0000261static inline void outl(uint32_t value, uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000262{
263 asm volatile ("outl %0,%w1": :"a" (value), "Nd" (port));
264}
265
Uwe Hermann43959702010-03-13 17:28:29 +0000266static inline uint32_t inl(uint16_t port)
Jonathan A. Kollasch3646c8f2010-01-08 21:18:08 +0000267{
268 uint32_t value;
269 asm volatile ("inl %1,%0":"=a" (value):"Nd" (port));
270 return value;
271}
272 #endif
273#endif
274
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000275#if !defined(__DARWIN__) && !defined(__FreeBSD__) && !defined(__DragonFly__)
276typedef struct { uint32_t hi, lo; } msr_t;
277msr_t rdmsr(int addr);
278int wrmsr(int addr, msr_t msr);
279#endif
280#if defined(__FreeBSD__) || defined(__DragonFly__)
281/* FreeBSD already has conflicting definitions for wrmsr/rdmsr. */
282#undef rdmsr
283#undef wrmsr
284#define rdmsr freebsd_rdmsr
285#define wrmsr freebsd_wrmsr
286typedef struct { uint32_t hi, lo; } msr_t;
287msr_t freebsd_rdmsr(int addr);
288int freebsd_wrmsr(int addr, msr_t msr);
289#endif
290
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000291#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || defined(__ppc64__)
292
293/* PCI port I/O is not yet implemented on PowerPC. */
294
295#elif defined (__mips) || defined (__mips__) || defined (_mips) || defined (mips)
296
297/* PCI port I/O is not yet implemented on MIPS. */
298
299#else
300
301#error Unknown architecture, please check if it supports PCI port IO.
302
303#endif
304
Carl-Daniel Hailfinger5d5c0722009-12-14 03:32:24 +0000305#endif /* !__HWACCESS_H__ */