iPXE
|
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 */