[ioapi] Formalise the I/O API as used in i386-pcbios
[people/asdlkf/gpxe.git] / src / include / gpxe / io.h
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 */