Browse Source

[ioapi] Formalise the I/O API as used in i386-pcbios

tags/v0.9.6
Michael Brown 15 years ago
parent
commit
8956a36be5

+ 93
- 0
src/arch/i386/core/x86_io.c View File

@@ -0,0 +1,93 @@
1
+/*
2
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <gpxe/io.h>
20
+#include <gpxe/x86_io.h>
21
+
22
+/** @file
23
+ *
24
+ * gPXE I/O API for x86
25
+ *
26
+ */
27
+
28
+/**
29
+ * Read 64-bit qword from memory-mapped device
30
+ *
31
+ * @v io_addr		I/O address
32
+ * @ret data		Value read
33
+ *
34
+ * This routine uses MMX instructions.
35
+ */
36
+static uint64_t x86_readq ( volatile uint64_t *io_addr ) {
37
+	uint64_t data;
38
+        __asm__ __volatile__ ( "pushl %%edx\n\t"
39
+			       "pushl %%eax\n\t"
40
+			       "movq (%1), %%mm0\n\t"
41
+			       "movq %%mm0, (%%esp)\n\t"
42
+			       "popl %%eax\n\t"
43
+			       "popl %%edx\n\t"
44
+			       "emms\n\t"
45
+                               : "=A" ( data ) : "r" ( io_addr ) );
46
+	return data;
47
+}
48
+
49
+/**
50
+ * Write 64-bit qword to memory-mapped device
51
+ *
52
+ * @v data		Value to write
53
+ * @v io_addr		I/O address
54
+ *
55
+ * This routine uses MMX instructions.
56
+ */
57
+static void x86_writeq ( uint64_t data, volatile uint64_t *io_addr ) {
58
+	__asm__ __volatile__ ( "pushl %%edx\n\t"
59
+			       "pushl %%eax\n\t"
60
+			       "movq (%%esp), %%mm0\n\t"
61
+			       "movq %%mm0, (%1)\n\t"
62
+			       "popl %%eax\n\t"
63
+			       "popl %%edx\n\t"
64
+			       "emms\n\t"
65
+			       : : "A" ( data ), "r" ( io_addr ) );
66
+}
67
+
68
+PROVIDE_IOAPI_INLINE ( x86, iounmap );
69
+PROVIDE_IOAPI_INLINE ( x86, io_to_bus );
70
+PROVIDE_IOAPI_INLINE ( x86, virt_to_bus );
71
+PROVIDE_IOAPI_INLINE ( x86, bus_to_virt );
72
+PROVIDE_IOAPI_INLINE ( x86, readb );
73
+PROVIDE_IOAPI_INLINE ( x86, readw );
74
+PROVIDE_IOAPI_INLINE ( x86, readl );
75
+PROVIDE_IOAPI ( x86, readq, x86_readq );
76
+PROVIDE_IOAPI_INLINE ( x86, writeb );
77
+PROVIDE_IOAPI_INLINE ( x86, writew );
78
+PROVIDE_IOAPI_INLINE ( x86, writel );
79
+PROVIDE_IOAPI ( x86, writeq, x86_writeq );
80
+PROVIDE_IOAPI_INLINE ( x86, inb );
81
+PROVIDE_IOAPI_INLINE ( x86, inw );
82
+PROVIDE_IOAPI_INLINE ( x86, inl );
83
+PROVIDE_IOAPI_INLINE ( x86, outb );
84
+PROVIDE_IOAPI_INLINE ( x86, outw );
85
+PROVIDE_IOAPI_INLINE ( x86, outl );
86
+PROVIDE_IOAPI_INLINE ( x86, insb );
87
+PROVIDE_IOAPI_INLINE ( x86, insw );
88
+PROVIDE_IOAPI_INLINE ( x86, insl );
89
+PROVIDE_IOAPI_INLINE ( x86, outsb );
90
+PROVIDE_IOAPI_INLINE ( x86, outsw );
91
+PROVIDE_IOAPI_INLINE ( x86, outsl );
92
+PROVIDE_IOAPI_INLINE ( x86, iodelay );
93
+PROVIDE_IOAPI_INLINE ( x86, mb );

+ 12
- 0
src/arch/i386/include/bits/io.h View File

@@ -0,0 +1,12 @@
1
+#ifndef _BITS_IO_H
2
+#define _BITS_IO_H
3
+
4
+/** @file
5
+ *
6
+ * i386-specific I/O API implementations
7
+ *
8
+ */
9
+
10
+#include <gpxe/x86_io.h>
11
+
12
+#endif /* _BITS_IO_H */

+ 148
- 0
src/arch/i386/include/gpxe/x86_io.h View File

@@ -0,0 +1,148 @@
1
+#ifndef _GPXE_X86_IO_H
2
+#define _GPXE_X86_IO_H
3
+
4
+/** @file
5
+ *
6
+ * gPXE I/O API for x86
7
+ *
8
+ * i386 uses direct pointer dereferences for accesses to memory-mapped
9
+ * I/O space, and the inX/outX instructions for accesses to
10
+ * port-mapped I/O space.
11
+ *
12
+ * 64-bit atomic accesses (readq() and writeq()) use MMX instructions,
13
+ * and will crash original Pentium and earlier CPUs.  Fortunately, no
14
+ * hardware that requires atomic 64-bit accesses will physically fit
15
+ * into a machine with such an old CPU anyway.
16
+ */
17
+
18
+#include <virtaddr.h>
19
+
20
+#ifdef IOAPI_X86
21
+#define IOAPI_PREFIX_x86
22
+#else
23
+#define IOAPI_PREFIX_x86 __x86_
24
+#endif
25
+
26
+/*
27
+ * Memory space mappings
28
+ *
29
+ */
30
+
31
+static inline __always_inline void *
32
+IOAPI_INLINE ( x86, ioremap ) ( unsigned long bus_addr, size_t len __unused ) {
33
+	return phys_to_virt ( bus_addr );
34
+}
35
+
36
+static inline __always_inline void
37
+IOAPI_INLINE ( x86, iounmap ) ( volatile const void *io_addr __unused ) {
38
+	/* Nothing to do */
39
+}
40
+
41
+static inline __always_inline unsigned long
42
+IOAPI_INLINE ( x86, io_to_bus ) ( volatile const void *io_addr ) {
43
+	return virt_to_phys ( io_addr );
44
+}
45
+
46
+static inline __always_inline unsigned long
47
+IOAPI_INLINE ( x86, virt_to_bus ) ( volatile const void *addr ) {
48
+	return virt_to_phys ( addr );
49
+}
50
+
51
+static inline __always_inline void *
52
+IOAPI_INLINE ( x86, bus_to_virt ) ( unsigned long bus_addr ) {
53
+	return phys_to_virt ( bus_addr );
54
+}
55
+
56
+/*
57
+ * MMIO reads and writes up to 32 bits
58
+ *
59
+ */
60
+
61
+#define X86_READX( _api_func, _type )					      \
62
+static inline __always_inline _type					      \
63
+IOAPI_INLINE ( x86, _api_func ) ( volatile _type *io_addr ) {		      \
64
+	return *io_addr;						      \
65
+}
66
+X86_READX ( readb, uint8_t );
67
+X86_READX ( readw, uint16_t );
68
+X86_READX ( readl, uint32_t );
69
+
70
+#define X86_WRITEX( _api_func, _type )					      \
71
+static inline __always_inline void					      \
72
+IOAPI_INLINE ( x86, _api_func ) ( _type data,				      \
73
+				  volatile _type *io_addr ) {		      \
74
+	*io_addr = data;						      \
75
+}
76
+X86_WRITEX ( writeb, uint8_t );
77
+X86_WRITEX ( writew, uint16_t );
78
+X86_WRITEX ( writel, uint32_t );
79
+
80
+/*
81
+ * PIO reads and writes up to 32 bits
82
+ *
83
+ */
84
+
85
+#define X86_INX( _insn_suffix, _type, _reg_prefix )			      \
86
+static inline __always_inline _type					      \
87
+IOAPI_INLINE ( x86, in ## _insn_suffix ) ( volatile _type *io_addr ) {	      \
88
+	_type data;							      \
89
+	__asm__ __volatile__ ( "in" #_insn_suffix " %w1, %" _reg_prefix "0"   \
90
+			       : "=a" ( data ) : "Nd" ( io_addr ) );	      \
91
+	return data;							      \
92
+}									      \
93
+static inline __always_inline void					      \
94
+IOAPI_INLINE ( x86, ins ## _insn_suffix ) ( volatile _type *io_addr,	      \
95
+					    _type *data,		      \
96
+					    unsigned int count ) {	      \
97
+	unsigned int discard_D;						      \
98
+	__asm__ __volatile__ ( "rep ins" #_insn_suffix			      \
99
+			       : "=D" ( discard_D )			      \
100
+			       : "d" ( io_addr ), "c" ( count ),	      \
101
+				 "0" ( data ) );			      \
102
+}
103
+X86_INX ( b, uint8_t, "b" );
104
+X86_INX ( w, uint16_t, "w" );
105
+X86_INX ( l, uint32_t, "k" );
106
+
107
+#define X86_OUTX( _insn_suffix, _type, _reg_prefix )			      \
108
+static inline __always_inline void					      \
109
+IOAPI_INLINE ( x86, out ## _insn_suffix ) ( _type data,			      \
110
+					    volatile _type *io_addr ) {	      \
111
+	__asm__ __volatile__ ( "out" #_insn_suffix " %" _reg_prefix "0, %w1"  \
112
+			       : : "a" ( data ), "Nd" ( io_addr ) );	      \
113
+}									      \
114
+static inline __always_inline void					      \
115
+IOAPI_INLINE ( x86, outs ## _insn_suffix ) ( volatile _type *io_addr,	      \
116
+					     const _type *data,		      \
117
+					     unsigned int count ) {	      \
118
+	unsigned int discard_D;						      \
119
+	__asm__ __volatile__ ( "rep outs" #_insn_suffix			      \
120
+			       : "=D" ( discard_D )			      \
121
+			       : "d" ( io_addr ), "c" ( count ),	      \
122
+				 "0" ( data ) );			      \
123
+}
124
+X86_OUTX ( b, uint8_t, "b" );
125
+X86_OUTX ( w, uint16_t, "w" );
126
+X86_OUTX ( l, uint32_t, "k" );
127
+
128
+/*
129
+ * Slow down I/O
130
+ *
131
+ */
132
+
133
+static inline __always_inline void
134
+IOAPI_INLINE ( x86, iodelay ) ( void ) {
135
+	__asm__ __volatile__ ( "outb %al, $0x80" );
136
+}
137
+
138
+/*
139
+ * Memory barrier
140
+ *
141
+ */
142
+
143
+static inline __always_inline void
144
+IOAPI_INLINE ( x86, mb ) ( void ) {
145
+	__asm__ __volatile__ ( "lock; addl $0, 0(%%esp)" : : : "memory" );
146
+}
147
+
148
+#endif /* _GPXE_X86_IO_H */

+ 8
- 0
src/config/defaults.h View File

@@ -0,0 +1,8 @@
1
+#ifndef CONFIG_DEFAULTS_H
2
+#define CONFIG_DEFAULTS_H
3
+
4
+#define CONFIG_DEFAULTS(_platform) <config/defaults/_platform.h>
5
+
6
+#include CONFIG_DEFAULTS(PLATFORM)
7
+
8
+#endif /* CONFIG_DEFAULTS_H */

+ 12
- 0
src/config/defaults/pcbios.h View File

@@ -0,0 +1,12 @@
1
+#ifndef CONFIG_DEFAULTS_PCBIOS_H
2
+#define CONFIG_DEFAULTS_PCBIOS_H
3
+
4
+/** @file
5
+ *
6
+ * Configuration defaults for PCBIOS
7
+ *
8
+ */
9
+
10
+#define IOAPI_X86
11
+
12
+#endif /* CONFIG_DEFAULTS_PCBIOS_H */

+ 12
- 0
src/config/ioapi.h View File

@@ -0,0 +1,12 @@
1
+#ifndef CONFIG_IOAPI_H
2
+#define CONFIG_IOAPI_H
3
+
4
+/** @file
5
+ *
6
+ * I/O API configuration
7
+ *
8
+ */
9
+
10
+#include <config/defaults.h>
11
+
12
+#endif /* CONFIG_IOAPI_H */

+ 82
- 0
src/include/gpxe/api.h View File

@@ -0,0 +1,82 @@
1
+#ifndef _GPXE_API_H
2
+#define _GPXE_API_H
3
+
4
+/** @file
5
+ *
6
+ * gPXE internal APIs
7
+ *
8
+ * There are various formally-defined APIs internal to gPXE, with
9
+ * several differing implementations specific to particular execution
10
+ * environments (e.g. PC BIOS, EFI, LinuxBIOS).
11
+ *
12
+ */
13
+
14
+/** @defgroup Single-implementation APIs
15
+ *
16
+ * These are APIs for which only a single implementation may be
17
+ * compiled in at any given time.
18
+ *
19
+ * @{
20
+ */
21
+
22
+/**
23
+ * Calculate function implementation name
24
+ *
25
+ * @v _prefix		Subsystem prefix
26
+ * @v _api_func		API function
27
+ * @ret _subsys_func	Subsystem API function
28
+ *
29
+ * The subsystem prefix should be an empty string for the currently
30
+ * selected subsystem, and should be a subsystem-unique string for all
31
+ * other subsystems.
32
+ */
33
+#define SINGLE_API_NAME( _prefix, _api_func ) _prefix ## _api_func
34
+
35
+/**
36
+ * Calculate static inline function name
37
+ *
38
+ * @v _prefix		Subsystem prefix
39
+ * @v _api_func		API function
40
+ * @ret _subsys_func	Subsystem API function
41
+ */
42
+#define SINGLE_API_INLINE( _prefix, _api_func )	\
43
+	SINGLE_API_NAME ( _prefix, _api_func )
44
+
45
+/**
46
+ * Provide an API implementation
47
+ *
48
+ * @v _prefix		Subsystem prefix
49
+ * @v _api_func		API function
50
+ * @v _func		Implementing function
51
+ */
52
+#define PROVIDE_SINGLE_API( _prefix, _api_func, _func )			      \
53
+	/* Ensure that _api_func exists */				      \
54
+	typeof ( _api_func ) _api_func;					      \
55
+	/* Ensure that _func exists */					      \
56
+	typeof ( _func ) _func;						      \
57
+	/* Ensure that _func is type-compatible with _api_func */	      \
58
+	typeof ( _api_func ) _func;					      \
59
+	/* Ensure that _subsys_func is non-static */			      \
60
+	extern typeof ( _api_func ) SINGLE_API_NAME ( _prefix, _api_func );   \
61
+	/* Provide symbol alias from _subsys_func to _func */		      \
62
+	typeof ( _api_func ) SINGLE_API_NAME ( _prefix, _api_func )	      \
63
+		__attribute__ (( alias ( #_func ) ));
64
+
65
+/**
66
+ * Provide a static inline API implementation
67
+ *
68
+ * @v _prefix		Subsystem prefix
69
+ * @v _api_func		API function
70
+ */
71
+#define PROVIDE_SINGLE_API_INLINE( _prefix, _api_func )			      \
72
+	/* Ensure that _api_func exists */				      \
73
+	typeof ( _api_func ) _api_func;					      \
74
+	/* Ensure that _subsys_func exists and is static */		      \
75
+	static typeof ( SINGLE_API_INLINE ( _prefix, _api_func ) )	      \
76
+		SINGLE_API_INLINE ( _prefix, _api_func );		      \
77
+	/* Ensure that _subsys_func is type-compatible with _api_func */      \
78
+	typeof ( _api_func ) SINGLE_API_INLINE ( _prefix, _api_func );
79
+
80
+/** @} */
81
+
82
+#endif /* _GPXE_API_H */

+ 483
- 0
src/include/gpxe/io.h View File

@@ -0,0 +1,483 @@
1
+#ifndef _GPXE_IO_H
2
+#define _GPXE_IO_H
3
+
4
+/** @file
5
+ *
6
+ * gPXE I/O API
7
+ *
8
+ * The I/O API provides methods for reading from and writing to
9
+ * memory-mapped and I/O-mapped devices.
10
+ *
11
+ * The standard methods (readl()/writel() etc.) do not strictly check
12
+ * the type of the address parameter; this is because traditional
13
+ * usage does not necessarily provide the correct pointer type.  For
14
+ * example, code written for ISA devices at fixed I/O addresses (such
15
+ * as the keyboard controller) tend to use plain integer constants for
16
+ * the address parameter.
17
+ */
18
+
19
+#include <stdint.h>
20
+#include <gpxe/api.h>
21
+#include <config/ioapi.h>
22
+
23
+/**
24
+ * Calculate static inline I/O API function name
25
+ *
26
+ * @v _prefix		Subsystem prefix
27
+ * @v _api_func		API function
28
+ * @ret _subsys_func	Subsystem API function
29
+ */
30
+#define IOAPI_INLINE( _subsys, _api_func ) \
31
+	SINGLE_API_INLINE ( IOAPI_PREFIX_ ## _subsys, _api_func )
32
+
33
+/**
34
+ * Provide an I/O API implementation
35
+ *
36
+ * @v _prefix		Subsystem prefix
37
+ * @v _api_func		API function
38
+ * @v _func		Implementing function
39
+ */
40
+#define PROVIDE_IOAPI( _subsys, _api_func, _func ) \
41
+	PROVIDE_SINGLE_API ( IOAPI_PREFIX_ ## _subsys, _api_func, _func )
42
+
43
+/**
44
+ * Provide a static inline I/O API implementation
45
+ *
46
+ * @v _prefix		Subsystem prefix
47
+ * @v _api_func		API function
48
+ */
49
+#define PROVIDE_IOAPI_INLINE( _subsys, _api_func ) \
50
+	PROVIDE_SINGLE_API_INLINE ( IOAPI_PREFIX_ ## _subsys, _api_func )
51
+
52
+/* Include all architecture-independent I/O API headers */
53
+
54
+/* Include all architecture-dependent I/O API headers */
55
+#include <bits/io.h>
56
+
57
+/**
58
+ * Wrap an I/O read
59
+ *
60
+ * @v _func		I/O API function
61
+ * @v _type		Data type
62
+ * @v io_addr		I/O address
63
+ * @v _prefix		Prefix for address in debug message
64
+ * @v _ndigits		Number of hex digits for this data type
65
+ */
66
+#define IOAPI_READ( _func, _type, io_addr, _prefix, _ndigits ) ( {	      \
67
+	volatile _type *_io_addr =					      \
68
+		( ( volatile _type * ) ( intptr_t ) (io_addr) );	      \
69
+	_type _data = _func ( _io_addr );				      \
70
+	DBGIO ( "[" _prefix " %08lx] => %0" #_ndigits "llx\n",		      \
71
+		io_to_bus ( _io_addr ), ( unsigned long long ) _data );	      \
72
+	_data; } )
73
+
74
+/**
75
+ * Wrap an I/O write
76
+ *
77
+ * @v _func		I/O API function
78
+ * @v _type		Data type
79
+ * @v data		Value to write
80
+ * @v io_addr		I/O address
81
+ * @v _prefix		Prefix for address in debug message
82
+ * @v _ndigits		Number of hex digits for this data type
83
+ */
84
+#define IOAPI_WRITE( _func, _type, data, io_addr, _prefix, _ndigits ) do {    \
85
+	volatile _type *_io_addr =					      \
86
+		( ( volatile _type * ) ( intptr_t ) (io_addr) );	      \
87
+	_type _data = (data);						      \
88
+	DBGIO ( "[" _prefix " %08lx] <= %0" #_ndigits "llx\n",		      \
89
+		io_to_bus ( _io_addr ), ( unsigned long long ) _data );	      \
90
+	_func ( _data, _io_addr );					      \
91
+	} while ( 0 )
92
+
93
+/**
94
+ * Wrap an I/O string read
95
+ *
96
+ * @v _func		I/O API function
97
+ * @v _type		Data type
98
+ * @v io_addr		I/O address
99
+ * @v data		Data buffer
100
+ * @v count		Number of elements to read
101
+ * @v _prefix		Prefix for address in debug message
102
+ * @v _ndigits		Number of hex digits for this data type
103
+ */
104
+#define IOAPI_READS( _func, _type, io_addr, data, count, _prefix, _ndigits )  \
105
+	do {								      \
106
+	volatile _type *_io_addr =					      \
107
+		( ( volatile _type * ) ( intptr_t ) (io_addr) );	      \
108
+	void *_data_void = (data); /* Check data is a pointer */	      \
109
+	_type * _data = ( ( _type * ) _data_void );			      \
110
+	const _type * _dbg_data = _data;				      \
111
+	unsigned int _count = (count);					      \
112
+	unsigned int _dbg_count = _count;				      \
113
+	_func ( _io_addr, _data, _count );				      \
114
+	DBGIO ( "[" _prefix " %08lx] =>", io_to_bus ( _io_addr ) );	      \
115
+	while ( _dbg_count-- ) {					      \
116
+		DBGIO ( " %0" #_ndigits "llx",				      \
117
+			( ( unsigned long long ) *(_dbg_data++) ) );	      \
118
+	}								      \
119
+	DBGIO ( "\n" );							      \
120
+	} while ( 0 )
121
+
122
+/**
123
+ * Wrap an I/O string write
124
+ *
125
+ * @v _func		I/O API function
126
+ * @v _type		Data type
127
+ * @v io_addr		I/O address
128
+ * @v data		Data buffer
129
+ * @v count		Number of elements to write
130
+ * @v _prefix		Prefix for address in debug message
131
+ * @v _ndigits		Number of hex digits for this data type
132
+ */
133
+#define IOAPI_WRITES( _func, _type, io_addr, data, count, _prefix, _ndigits ) \
134
+	do {								      \
135
+	volatile _type *_io_addr =					      \
136
+		( ( volatile _type * ) ( intptr_t ) (io_addr) );	      \
137
+	const void *_data_void = (data); /* Check data is a pointer */	      \
138
+	const _type * _data = ( ( const _type * ) _data_void );		      \
139
+	const _type * _dbg_data = _data;				      \
140
+	unsigned int _count = (count);					      \
141
+	unsigned int _dbg_count = _count;				      \
142
+	DBGIO ( "[" _prefix " %08lx] <=", io_to_bus ( _io_addr ) );	      \
143
+	while ( _dbg_count-- ) {					      \
144
+		DBGIO ( " %0" #_ndigits "llx",				      \
145
+			( ( unsigned long long ) *(_dbg_data++) ) );	      \
146
+	}								      \
147
+	DBGIO ( "\n" );							      \
148
+	_func ( _io_addr, _data, _count );				      \
149
+	} while ( 0 )
150
+
151
+/**
152
+ * Map bus address as an I/O address
153
+ *
154
+ * @v bus_addr		Bus address
155
+ * @v len		Length of region
156
+ * @ret io_addr		I/O address
157
+ */
158
+void * ioremap ( unsigned long bus_addr, size_t len );
159
+
160
+/**
161
+ * Unmap I/O address
162
+ *
163
+ * @v io_addr		I/O address
164
+ */
165
+void iounmap ( volatile const void *io_addr );
166
+
167
+/**
168
+ * Convert I/O address to bus address (for debug only)
169
+ *
170
+ * @v io_addr		I/O address
171
+ * @ret bus_addr	Bus address
172
+ */
173
+unsigned long io_to_bus ( volatile const void *io_addr );
174
+
175
+/**
176
+ * Convert virtual address to a bus address
177
+ *
178
+ * @v addr		Virtual address
179
+ * @ret bus_addr	Bus address
180
+ */
181
+unsigned long virt_to_bus ( volatile const void *addr );
182
+
183
+/**
184
+ * Convert bus address to a virtual address
185
+ *
186
+ * @v bus_addr		Bus address
187
+ * @ret addr		Virtual address
188
+ *
189
+ * This operation isn't actually valid within our memory model, and is
190
+ * impossible to achieve under -DKEEP_IT_REAL.  Some drivers haven't
191
+ * been updated to avoid it yet, though.
192
+ */
193
+void * bus_to_virt ( unsigned long bus_addr );
194
+
195
+/**
196
+ * Read byte from memory-mapped device
197
+ *
198
+ * @v io_addr		I/O address
199
+ * @ret data		Value read
200
+ */
201
+uint8_t readb ( volatile uint8_t *io_addr );
202
+#define readb( io_addr ) IOAPI_READ ( readb, uint8_t, io_addr, "MEM", 2 )
203
+
204
+/**
205
+ * Read 16-bit word from memory-mapped device
206
+ *
207
+ * @v io_addr		I/O address
208
+ * @ret data		Value read
209
+ */
210
+uint16_t readw ( volatile uint16_t *io_addr );
211
+#define readw( io_addr ) IOAPI_READ ( readw, uint16_t, io_addr, "MEM", 4 )
212
+
213
+/**
214
+ * Read 32-bit dword from memory-mapped device
215
+ *
216
+ * @v io_addr		I/O address
217
+ * @ret data		Value read
218
+ */
219
+uint32_t readl ( volatile uint32_t *io_addr );
220
+#define readl( io_addr ) IOAPI_READ ( readl, uint32_t, io_addr, "MEM", 8 )
221
+
222
+/**
223
+ * Read 64-bit qword from memory-mapped device
224
+ *
225
+ * @v io_addr		I/O address
226
+ * @ret data		Value read
227
+ */
228
+uint64_t readq ( volatile uint64_t *io_addr );
229
+#define readq( io_addr ) IOAPI_READ ( readq, uint64_t, io_addr, "MEM", 16 )
230
+
231
+/**
232
+ * Write byte to memory-mapped device
233
+ *
234
+ * @v data		Value to write
235
+ * @v io_addr		I/O address
236
+ */
237
+void writeb ( uint8_t data, volatile uint8_t *io_addr );
238
+#define writeb( data, io_addr ) \
239
+	IOAPI_WRITE ( writeb, uint8_t, data, io_addr, "MEM", 2 )
240
+
241
+/**
242
+ * Write 16-bit word to memory-mapped device
243
+ *
244
+ * @v data		Value to write
245
+ * @v io_addr		I/O address
246
+ */
247
+void writew ( uint16_t data, volatile uint16_t *io_addr );
248
+#define writew( data, io_addr ) \
249
+	IOAPI_WRITE ( writew, uint16_t, data, io_addr, "MEM", 4 )
250
+
251
+/**
252
+ * Write 32-bit dword to memory-mapped device
253
+ *
254
+ * @v data		Value to write
255
+ * @v io_addr		I/O address
256
+ */
257
+void writel ( uint32_t data, volatile uint32_t *io_addr );
258
+#define writel( data, io_addr ) \
259
+	IOAPI_WRITE ( writel, uint32_t, data, io_addr, "MEM", 8 )
260
+
261
+/**
262
+ * Write 64-bit qword to memory-mapped device
263
+ *
264
+ * @v data		Value to write
265
+ * @v io_addr		I/O address
266
+ */
267
+void writeq ( uint64_t data, volatile uint64_t *io_addr );
268
+#define writeq( data, io_addr ) \
269
+	IOAPI_WRITE ( writeq, uint64_t, data, io_addr, "MEM", 16 )
270
+
271
+/**
272
+ * Read byte from I/O-mapped device
273
+ *
274
+ * @v io_addr		I/O address
275
+ * @ret data		Value read
276
+ */
277
+uint8_t inb ( volatile uint8_t *io_addr );
278
+#define inb( io_addr ) IOAPI_READ ( inb, uint8_t, io_addr, "IO", 2 )
279
+
280
+/**
281
+ * Read 16-bit word from I/O-mapped device
282
+ *
283
+ * @v io_addr		I/O address
284
+ * @ret data		Value read
285
+ */
286
+uint16_t inw ( volatile uint16_t *io_addr );
287
+#define inw( io_addr ) IOAPI_READ ( inw, uint16_t, io_addr, "IO", 4 )
288
+
289
+/**
290
+ * Read 32-bit dword from I/O-mapped device
291
+ *
292
+ * @v io_addr		I/O address
293
+ * @ret data		Value read
294
+ */
295
+uint32_t inl ( volatile uint32_t *io_addr );
296
+#define inl( io_addr ) IOAPI_READ ( inl, uint32_t, io_addr, "IO", 8 )
297
+
298
+/**
299
+ * Write byte to I/O-mapped device
300
+ *
301
+ * @v data		Value to write
302
+ * @v io_addr		I/O address
303
+ */
304
+void outb ( uint8_t data, volatile uint8_t *io_addr );
305
+#define outb( data, io_addr ) \
306
+	IOAPI_WRITE ( outb, uint8_t, data, io_addr, "IO", 2 )
307
+
308
+/**
309
+ * Write 16-bit word to I/O-mapped device
310
+ *
311
+ * @v data		Value to write
312
+ * @v io_addr		I/O address
313
+ */
314
+void outw ( uint16_t data, volatile uint16_t *io_addr );
315
+#define outw( data, io_addr ) \
316
+	IOAPI_WRITE ( outw, uint16_t, data, io_addr, "IO", 4 )
317
+
318
+/**
319
+ * Write 32-bit dword to I/O-mapped device
320
+ *
321
+ * @v data		Value to write
322
+ * @v io_addr		I/O address
323
+ */
324
+void outl ( uint32_t data, volatile uint32_t *io_addr );
325
+#define outl( data, io_addr ) \
326
+	IOAPI_WRITE ( outl, uint32_t, data, io_addr, "IO", 8 )
327
+
328
+/**
329
+ * Read bytes from I/O-mapped device
330
+ *
331
+ * @v io_addr		I/O address
332
+ * @v data		Data buffer
333
+ * @v count		Number of bytes to read
334
+ */
335
+void insb ( volatile uint8_t *io_addr, uint8_t *data, unsigned int count );
336
+#define insb( io_addr, data, count ) \
337
+	IOAPI_READS ( insb, uint8_t, io_addr, data, count, "IO", 2 )
338
+
339
+/**
340
+ * Read 16-bit words from I/O-mapped device
341
+ *
342
+ * @v io_addr		I/O address
343
+ * @v data		Data buffer
344
+ * @v count		Number of words to read
345
+ */
346
+void insw ( volatile uint16_t *io_addr, uint16_t *data, unsigned int count );
347
+#define insw( io_addr, data, count ) \
348
+	IOAPI_READS ( insw, uint16_t, io_addr, data, count, "IO", 4 )
349
+
350
+/**
351
+ * Read 32-bit words from I/O-mapped device
352
+ *
353
+ * @v io_addr		I/O address
354
+ * @v data		Data buffer
355
+ * @v count		Number of words to read
356
+ */
357
+void insl ( volatile uint32_t *io_addr, uint32_t *data, unsigned int count );
358
+#define insl( io_addr, data, count ) \
359
+	IOAPI_READS ( insl, uint32_t, io_addr, data, count, "IO", 8 )
360
+
361
+/**
362
+ * Write bytes to I/O-mapped device
363
+ *
364
+ * @v io_addr		I/O address
365
+ * @v data		Data buffer
366
+ * @v count		Number of bytes to write
367
+ */
368
+void outsb ( volatile uint8_t *io_addr, const uint8_t *data,
369
+	     unsigned int count );
370
+#define outsb( io_addr, data, count ) \
371
+	IOAPI_WRITES ( outsb, uint8_t, io_addr, data, count, "IO", 2 )
372
+
373
+/**
374
+ * Write 16-bit words to I/O-mapped device
375
+ *
376
+ * @v io_addr		I/O address
377
+ * @v data		Data buffer
378
+ * @v count		Number of words to write
379
+ */
380
+void outsw ( volatile uint16_t *io_addr, const uint16_t *data,
381
+	     unsigned int count );
382
+#define outsw( io_addr, data, count ) \
383
+	IOAPI_WRITES ( outsw, uint16_t, io_addr, data, count, "IO", 4 )
384
+
385
+/**
386
+ * Write 32-bit words to I/O-mapped device
387
+ *
388
+ * @v io_addr		I/O address
389
+ * @v data		Data buffer
390
+ * @v count		Number of words to write
391
+ */
392
+void outsl ( volatile uint32_t *io_addr, const uint32_t *data,
393
+	     unsigned int count );
394
+#define outsl( io_addr, data, count ) \
395
+	IOAPI_WRITES ( outsl, uint32_t, io_addr, data, count, "IO", 8 )
396
+
397
+/**
398
+ * Slow down I/O
399
+ *
400
+ */
401
+void iodelay ( void );
402
+
403
+/**
404
+ * Read value from I/O-mapped device, slowly
405
+ *
406
+ * @v _func		Function to use to read value
407
+ * @v data		Value to write
408
+ * @v io_addr		I/O address
409
+ */
410
+#define INX_P( _func, _type, io_addr ) ( {				      \
411
+	_type _data = _func ( (io_addr) );				      \
412
+	iodelay();							      \
413
+	_data; } )
414
+
415
+/**
416
+ * Read byte from I/O-mapped device
417
+ *
418
+ * @v io_addr		I/O address
419
+ * @ret data		Value read
420
+ */
421
+#define inb_p( io_addr ) INX_P ( inb, uint8_t, io_addr )
422
+
423
+/**
424
+ * Read 16-bit word from I/O-mapped device
425
+ *
426
+ * @v io_addr		I/O address
427
+ * @ret data		Value read
428
+ */
429
+#define inw_p( io_addr ) INX_P ( inw, uint16_t, io_addr )
430
+
431
+/**
432
+ * Read 32-bit dword from I/O-mapped device
433
+ *
434
+ * @v io_addr		I/O address
435
+ * @ret data		Value read
436
+ */
437
+#define inl_p( io_addr ) INX_P ( inl, uint32_t, io_addr )
438
+
439
+/**
440
+ * Write value to I/O-mapped device, slowly
441
+ *
442
+ * @v _func		Function to use to write value
443
+ * @v data		Value to write
444
+ * @v io_addr		I/O address
445
+ */
446
+#define OUTX_P( _func, data, io_addr ) do {				      \
447
+	_func ( (data), (io_addr) );					      \
448
+	iodelay();							      \
449
+	} while ( 0 )
450
+
451
+/**
452
+ * Write byte to I/O-mapped device, slowly
453
+ *
454
+ * @v data		Value to write
455
+ * @v io_addr		I/O address
456
+ */
457
+#define outb_p( data, io_addr ) OUTX_P ( outb, data, io_addr )
458
+
459
+/**
460
+ * Write 16-bit word to I/O-mapped device, slowly
461
+ *
462
+ * @v data		Value to write
463
+ * @v io_addr		I/O address
464
+ */
465
+#define outw_p( data, io_addr ) OUTX_P ( outw, data, io_addr )
466
+
467
+/**
468
+ * Write 32-bit dword to I/O-mapped device, slowly
469
+ *
470
+ * @v data		Value to write
471
+ * @v io_addr		I/O address
472
+ */
473
+#define outl_p( data, io_addr ) OUTX_P ( outl, data, io_addr )
474
+
475
+/**
476
+ * Memory barrier
477
+ *
478
+ */
479
+void mb ( void );
480
+#define rmb()	mb()
481
+#define wmb()	mb()
482
+
483
+#endif /* _GPXE_IO_H */

Loading…
Cancel
Save