iPXE
io.h
Go to the documentation of this file.
00001 #ifndef _IPXE_IO_H
00002 #define _IPXE_IO_H
00003 
00004 /** @file
00005  *
00006  * iPXE I/O API
00007  *
00008  * The I/O API provides methods for reading from and writing to
00009  * memory-mapped and I/O-mapped devices.
00010  *
00011  * The standard methods (readl()/writel() etc.) do not strictly check
00012  * the type of the address parameter; this is because traditional
00013  * usage does not necessarily provide the correct pointer type.  For
00014  * example, code written for ISA devices at fixed I/O addresses (such
00015  * as the keyboard controller) tend to use plain integer constants for
00016  * the address parameter.
00017  */
00018 
00019 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00020 
00021 #include <stdint.h>
00022 #include <ipxe/api.h>
00023 #include <ipxe/iomap.h>
00024 #include <config/ioapi.h>
00025 
00026 /** Page size */
00027 #define PAGE_SIZE ( 1 << PAGE_SHIFT )
00028 
00029 /** Page mask */
00030 #define PAGE_MASK ( PAGE_SIZE - 1 )
00031 
00032 /**
00033  * Calculate static inline I/O API function name
00034  *
00035  * @v _prefix           Subsystem prefix
00036  * @v _api_func         API function
00037  * @ret _subsys_func    Subsystem API function
00038  */
00039 #define IOAPI_INLINE( _subsys, _api_func ) \
00040         SINGLE_API_INLINE ( IOAPI_PREFIX_ ## _subsys, _api_func )
00041 
00042 /**
00043  * Provide an I/O API implementation
00044  *
00045  * @v _prefix           Subsystem prefix
00046  * @v _api_func         API function
00047  * @v _func             Implementing function
00048  */
00049 #define PROVIDE_IOAPI( _subsys, _api_func, _func ) \
00050         PROVIDE_SINGLE_API ( IOAPI_PREFIX_ ## _subsys, _api_func, _func )
00051 
00052 /**
00053  * Provide a static inline I/O API implementation
00054  *
00055  * @v _prefix           Subsystem prefix
00056  * @v _api_func         API function
00057  */
00058 #define PROVIDE_IOAPI_INLINE( _subsys, _api_func ) \
00059         PROVIDE_SINGLE_API_INLINE ( IOAPI_PREFIX_ ## _subsys, _api_func )
00060 
00061 /* Include all architecture-independent I/O API headers */
00062 
00063 /* Include all architecture-dependent I/O API headers */
00064 #include <bits/io.h>
00065 
00066 /**
00067  * Wrap an I/O read
00068  *
00069  * @v _func             I/O API function
00070  * @v _type             Data type
00071  * @v io_addr           I/O address
00072  * @v _prefix           Prefix for address in debug message
00073  * @v _ndigits          Number of hex digits for this data type
00074  */
00075 #define IOAPI_READ( _func, _type, io_addr, _prefix, _ndigits ) ( {            \
00076         volatile _type *_io_addr =                                            \
00077                 ( ( volatile _type * ) ( intptr_t ) (io_addr) );              \
00078         _type _data = _func ( _io_addr );                                     \
00079         DBGIO ( "[" _prefix " %08lx] => %0" #_ndigits "llx\n",                \
00080                 io_to_bus ( _io_addr ), ( unsigned long long ) _data );       \
00081         _data; } )
00082 
00083 /**
00084  * Wrap an I/O write
00085  *
00086  * @v _func             I/O API function
00087  * @v _type             Data type
00088  * @v data              Value to write
00089  * @v io_addr           I/O address
00090  * @v _prefix           Prefix for address in debug message
00091  * @v _ndigits          Number of hex digits for this data type
00092  */
00093 #define IOAPI_WRITE( _func, _type, data, io_addr, _prefix, _ndigits ) do {    \
00094         volatile _type *_io_addr =                                            \
00095                 ( ( volatile _type * ) ( intptr_t ) (io_addr) );              \
00096         _type _data = (data);                                                 \
00097         DBGIO ( "[" _prefix " %08lx] <= %0" #_ndigits "llx\n",                \
00098                 io_to_bus ( _io_addr ), ( unsigned long long ) _data );       \
00099         _func ( _data, _io_addr );                                            \
00100         } while ( 0 )
00101 
00102 /**
00103  * Wrap an I/O string read
00104  *
00105  * @v _func             I/O API function
00106  * @v _type             Data type
00107  * @v io_addr           I/O address
00108  * @v data              Data buffer
00109  * @v count             Number of elements to read
00110  * @v _prefix           Prefix for address in debug message
00111  * @v _ndigits          Number of hex digits for this data type
00112  */
00113 #define IOAPI_READS( _func, _type, io_addr, data, count, _prefix, _ndigits )  \
00114         do {                                                                  \
00115         volatile _type *_io_addr =                                            \
00116                 ( ( volatile _type * ) ( intptr_t ) (io_addr) );              \
00117         void *_data_void = (data); /* Check data is a pointer */              \
00118         _type * _data = ( ( _type * ) _data_void );                           \
00119         const _type * _dbg_data = _data;                                      \
00120         unsigned int _count = (count);                                        \
00121         unsigned int _dbg_count = _count;                                     \
00122         _func ( _io_addr, _data, _count );                                    \
00123         DBGIO ( "[" _prefix " %08lx] =>", io_to_bus ( _io_addr ) );           \
00124         while ( _dbg_count-- ) {                                              \
00125                 DBGIO ( " %0" #_ndigits "llx",                                \
00126                         ( ( unsigned long long ) *(_dbg_data++) ) );          \
00127         }                                                                     \
00128         DBGIO ( "\n" );                                                       \
00129         } while ( 0 )
00130 
00131 /**
00132  * Wrap an I/O string write
00133  *
00134  * @v _func             I/O API function
00135  * @v _type             Data type
00136  * @v io_addr           I/O address
00137  * @v data              Data buffer
00138  * @v count             Number of elements to write
00139  * @v _prefix           Prefix for address in debug message
00140  * @v _ndigits          Number of hex digits for this data type
00141  */
00142 #define IOAPI_WRITES( _func, _type, io_addr, data, count, _prefix, _ndigits ) \
00143         do {                                                                  \
00144         volatile _type *_io_addr =                                            \
00145                 ( ( volatile _type * ) ( intptr_t ) (io_addr) );              \
00146         const void *_data_void = (data); /* Check data is a pointer */        \
00147         const _type * _data = ( ( const _type * ) _data_void );               \
00148         const _type * _dbg_data = _data;                                      \
00149         unsigned int _count = (count);                                        \
00150         unsigned int _dbg_count = _count;                                     \
00151         DBGIO ( "[" _prefix " %08lx] <=", io_to_bus ( _io_addr ) );           \
00152         while ( _dbg_count-- ) {                                              \
00153                 DBGIO ( " %0" #_ndigits "llx",                                \
00154                         ( ( unsigned long long ) *(_dbg_data++) ) );          \
00155         }                                                                     \
00156         DBGIO ( "\n" );                                                       \
00157         _func ( _io_addr, _data, _count );                                    \
00158         } while ( 0 )
00159 
00160 /**
00161  * Convert physical address to a bus address
00162  *
00163  * @v phys_addr         Physical address
00164  * @ret bus_addr        Bus address
00165  */
00166 unsigned long phys_to_bus ( unsigned long phys_addr );
00167 
00168 /**
00169  * Convert bus address to a physical address
00170  *
00171  * @v bus_addr          Bus address
00172  * @ret phys_addr       Physical address
00173  */
00174 unsigned long bus_to_phys ( unsigned long bus_addr );
00175 
00176 /**
00177  * Convert virtual address to a bus address
00178  *
00179  * @v addr              Virtual address
00180  * @ret bus_addr        Bus address
00181  */
00182 static inline __always_inline unsigned long
00183 virt_to_bus ( volatile const void *addr ) {
00184         return phys_to_bus ( virt_to_phys ( addr ) );
00185 }
00186 
00187 /**
00188  * Convert bus address to a virtual address
00189  *
00190  * @v bus_addr          Bus address
00191  * @ret addr            Virtual address
00192  *
00193  * This operation is not available under all memory models.
00194  */
00195 static inline __always_inline void * bus_to_virt ( unsigned long bus_addr ) {
00196         return phys_to_virt ( bus_to_phys ( bus_addr ) );
00197 }
00198 
00199 /**
00200  * Read byte from memory-mapped device
00201  *
00202  * @v io_addr           I/O address
00203  * @ret data            Value read
00204  */
00205 uint8_t readb ( volatile uint8_t *io_addr );
00206 #define readb( io_addr ) IOAPI_READ ( readb, uint8_t, io_addr, "MEM", 2 )
00207 
00208 /**
00209  * Read 16-bit word from memory-mapped device
00210  *
00211  * @v io_addr           I/O address
00212  * @ret data            Value read
00213  */
00214 uint16_t readw ( volatile uint16_t *io_addr );
00215 #define readw( io_addr ) IOAPI_READ ( readw, uint16_t, io_addr, "MEM", 4 )
00216 
00217 /**
00218  * Read 32-bit dword from memory-mapped device
00219  *
00220  * @v io_addr           I/O address
00221  * @ret data            Value read
00222  */
00223 uint32_t readl ( volatile uint32_t *io_addr );
00224 #define readl( io_addr ) IOAPI_READ ( readl, uint32_t, io_addr, "MEM", 8 )
00225 
00226 /**
00227  * Read 64-bit qword from memory-mapped device
00228  *
00229  * @v io_addr           I/O address
00230  * @ret data            Value read
00231  */
00232 uint64_t readq ( volatile uint64_t *io_addr );
00233 #define readq( io_addr ) IOAPI_READ ( readq, uint64_t, io_addr, "MEM", 16 )
00234 
00235 /**
00236  * Write byte to memory-mapped device
00237  *
00238  * @v data              Value to write
00239  * @v io_addr           I/O address
00240  */
00241 void writeb ( uint8_t data, volatile uint8_t *io_addr );
00242 #define writeb( data, io_addr ) \
00243         IOAPI_WRITE ( writeb, uint8_t, data, io_addr, "MEM", 2 )
00244 
00245 /**
00246  * Write 16-bit word to memory-mapped device
00247  *
00248  * @v data              Value to write
00249  * @v io_addr           I/O address
00250  */
00251 void writew ( uint16_t data, volatile uint16_t *io_addr );
00252 #define writew( data, io_addr ) \
00253         IOAPI_WRITE ( writew, uint16_t, data, io_addr, "MEM", 4 )
00254 
00255 /**
00256  * Write 32-bit dword to memory-mapped device
00257  *
00258  * @v data              Value to write
00259  * @v io_addr           I/O address
00260  */
00261 void writel ( uint32_t data, volatile uint32_t *io_addr );
00262 #define writel( data, io_addr ) \
00263         IOAPI_WRITE ( writel, uint32_t, data, io_addr, "MEM", 8 )
00264 
00265 /**
00266  * Write 64-bit qword to memory-mapped device
00267  *
00268  * @v data              Value to write
00269  * @v io_addr           I/O address
00270  */
00271 void writeq ( uint64_t data, volatile uint64_t *io_addr );
00272 #define writeq( data, io_addr ) \
00273         IOAPI_WRITE ( writeq, uint64_t, data, io_addr, "MEM", 16 )
00274 
00275 /**
00276  * Read byte from I/O-mapped device
00277  *
00278  * @v io_addr           I/O address
00279  * @ret data            Value read
00280  */
00281 uint8_t inb ( volatile uint8_t *io_addr );
00282 #define inb( io_addr ) IOAPI_READ ( inb, uint8_t, io_addr, "IO", 2 )
00283 
00284 /**
00285  * Read 16-bit word from I/O-mapped device
00286  *
00287  * @v io_addr           I/O address
00288  * @ret data            Value read
00289  */
00290 uint16_t inw ( volatile uint16_t *io_addr );
00291 #define inw( io_addr ) IOAPI_READ ( inw, uint16_t, io_addr, "IO", 4 )
00292 
00293 /**
00294  * Read 32-bit dword from I/O-mapped device
00295  *
00296  * @v io_addr           I/O address
00297  * @ret data            Value read
00298  */
00299 uint32_t inl ( volatile uint32_t *io_addr );
00300 #define inl( io_addr ) IOAPI_READ ( inl, uint32_t, io_addr, "IO", 8 )
00301 
00302 /**
00303  * Write byte to I/O-mapped device
00304  *
00305  * @v data              Value to write
00306  * @v io_addr           I/O address
00307  */
00308 void outb ( uint8_t data, volatile uint8_t *io_addr );
00309 #define outb( data, io_addr ) \
00310         IOAPI_WRITE ( outb, uint8_t, data, io_addr, "IO", 2 )
00311 
00312 /**
00313  * Write 16-bit word to I/O-mapped device
00314  *
00315  * @v data              Value to write
00316  * @v io_addr           I/O address
00317  */
00318 void outw ( uint16_t data, volatile uint16_t *io_addr );
00319 #define outw( data, io_addr ) \
00320         IOAPI_WRITE ( outw, uint16_t, data, io_addr, "IO", 4 )
00321 
00322 /**
00323  * Write 32-bit dword to I/O-mapped device
00324  *
00325  * @v data              Value to write
00326  * @v io_addr           I/O address
00327  */
00328 void outl ( uint32_t data, volatile uint32_t *io_addr );
00329 #define outl( data, io_addr ) \
00330         IOAPI_WRITE ( outl, uint32_t, data, io_addr, "IO", 8 )
00331 
00332 /**
00333  * Read bytes from I/O-mapped device
00334  *
00335  * @v io_addr           I/O address
00336  * @v data              Data buffer
00337  * @v count             Number of bytes to read
00338  */
00339 void insb ( volatile uint8_t *io_addr, uint8_t *data, unsigned int count );
00340 #define insb( io_addr, data, count ) \
00341         IOAPI_READS ( insb, uint8_t, io_addr, data, count, "IO", 2 )
00342 
00343 /**
00344  * Read 16-bit words from I/O-mapped device
00345  *
00346  * @v io_addr           I/O address
00347  * @v data              Data buffer
00348  * @v count             Number of words to read
00349  */
00350 void insw ( volatile uint16_t *io_addr, uint16_t *data, unsigned int count );
00351 #define insw( io_addr, data, count ) \
00352         IOAPI_READS ( insw, uint16_t, io_addr, data, count, "IO", 4 )
00353 
00354 /**
00355  * Read 32-bit words from I/O-mapped device
00356  *
00357  * @v io_addr           I/O address
00358  * @v data              Data buffer
00359  * @v count             Number of words to read
00360  */
00361 void insl ( volatile uint32_t *io_addr, uint32_t *data, unsigned int count );
00362 #define insl( io_addr, data, count ) \
00363         IOAPI_READS ( insl, uint32_t, io_addr, data, count, "IO", 8 )
00364 
00365 /**
00366  * Write bytes to I/O-mapped device
00367  *
00368  * @v io_addr           I/O address
00369  * @v data              Data buffer
00370  * @v count             Number of bytes to write
00371  */
00372 void outsb ( volatile uint8_t *io_addr, const uint8_t *data,
00373              unsigned int count );
00374 #define outsb( io_addr, data, count ) \
00375         IOAPI_WRITES ( outsb, uint8_t, io_addr, data, count, "IO", 2 )
00376 
00377 /**
00378  * Write 16-bit words to I/O-mapped device
00379  *
00380  * @v io_addr           I/O address
00381  * @v data              Data buffer
00382  * @v count             Number of words to write
00383  */
00384 void outsw ( volatile uint16_t *io_addr, const uint16_t *data,
00385              unsigned int count );
00386 #define outsw( io_addr, data, count ) \
00387         IOAPI_WRITES ( outsw, uint16_t, io_addr, data, count, "IO", 4 )
00388 
00389 /**
00390  * Write 32-bit words to I/O-mapped device
00391  *
00392  * @v io_addr           I/O address
00393  * @v data              Data buffer
00394  * @v count             Number of words to write
00395  */
00396 void outsl ( volatile uint32_t *io_addr, const uint32_t *data,
00397              unsigned int count );
00398 #define outsl( io_addr, data, count ) \
00399         IOAPI_WRITES ( outsl, uint32_t, io_addr, data, count, "IO", 8 )
00400 
00401 /**
00402  * Slow down I/O
00403  *
00404  */
00405 void iodelay ( void );
00406 
00407 /**
00408  * Read value from I/O-mapped device, slowly
00409  *
00410  * @v _func             Function to use to read value
00411  * @v data              Value to write
00412  * @v io_addr           I/O address
00413  */
00414 #define INX_P( _func, _type, io_addr ) ( {                                    \
00415         _type _data = _func ( (io_addr) );                                    \
00416         iodelay();                                                            \
00417         _data; } )
00418 
00419 /**
00420  * Read byte from I/O-mapped device
00421  *
00422  * @v io_addr           I/O address
00423  * @ret data            Value read
00424  */
00425 #define inb_p( io_addr ) INX_P ( inb, uint8_t, io_addr )
00426 
00427 /**
00428  * Read 16-bit word from I/O-mapped device
00429  *
00430  * @v io_addr           I/O address
00431  * @ret data            Value read
00432  */
00433 #define inw_p( io_addr ) INX_P ( inw, uint16_t, io_addr )
00434 
00435 /**
00436  * Read 32-bit dword from I/O-mapped device
00437  *
00438  * @v io_addr           I/O address
00439  * @ret data            Value read
00440  */
00441 #define inl_p( io_addr ) INX_P ( inl, uint32_t, io_addr )
00442 
00443 /**
00444  * Write value to I/O-mapped device, slowly
00445  *
00446  * @v _func             Function to use to write value
00447  * @v data              Value to write
00448  * @v io_addr           I/O address
00449  */
00450 #define OUTX_P( _func, data, io_addr ) do {                                   \
00451         _func ( (data), (io_addr) );                                          \
00452         iodelay();                                                            \
00453         } while ( 0 )
00454 
00455 /**
00456  * Write byte to I/O-mapped device, slowly
00457  *
00458  * @v data              Value to write
00459  * @v io_addr           I/O address
00460  */
00461 #define outb_p( data, io_addr ) OUTX_P ( outb, data, io_addr )
00462 
00463 /**
00464  * Write 16-bit word to I/O-mapped device, slowly
00465  *
00466  * @v data              Value to write
00467  * @v io_addr           I/O address
00468  */
00469 #define outw_p( data, io_addr ) OUTX_P ( outw, data, io_addr )
00470 
00471 /**
00472  * Write 32-bit dword to I/O-mapped device, slowly
00473  *
00474  * @v data              Value to write
00475  * @v io_addr           I/O address
00476  */
00477 #define outl_p( data, io_addr ) OUTX_P ( outl, data, io_addr )
00478 
00479 /**
00480  * Memory barrier
00481  *
00482  */
00483 void mb ( void );
00484 #define rmb()   mb()
00485 #define wmb()   mb()
00486 
00487 /** A usable memory region */
00488 struct memory_region {
00489         /** Physical start address */
00490         uint64_t start;
00491         /** Physical end address */
00492         uint64_t end;
00493 };
00494 
00495 /** Maximum number of memory regions we expect to encounter */
00496 #define MAX_MEMORY_REGIONS 8
00497 
00498 /** A memory map */
00499 struct memory_map {
00500         /** Memory regions */
00501         struct memory_region regions[MAX_MEMORY_REGIONS];
00502         /** Number of used regions */
00503         unsigned int count;
00504 };
00505 
00506 /**
00507  * Get memory map
00508  *
00509  * @v memmap            Memory map to fill in
00510  */
00511 void get_memmap ( struct memory_map *memmap );
00512 
00513 #endif /* _IPXE_IO_H */