123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- #ifndef _GPXE_IO_H
- #define _GPXE_IO_H
-
- /** @file
- *
- * gPXE I/O API
- *
- * The I/O API provides methods for reading from and writing to
- * memory-mapped and I/O-mapped devices.
- *
- * The standard methods (readl()/writel() etc.) do not strictly check
- * the type of the address parameter; this is because traditional
- * usage does not necessarily provide the correct pointer type. For
- * example, code written for ISA devices at fixed I/O addresses (such
- * as the keyboard controller) tend to use plain integer constants for
- * the address parameter.
- */
-
- FILE_LICENCE ( GPL2_OR_LATER );
-
- #include <stdint.h>
- #include <gpxe/api.h>
- #include <config/ioapi.h>
- #include <gpxe/uaccess.h>
-
- /**
- * Calculate static inline I/O API function name
- *
- * @v _prefix Subsystem prefix
- * @v _api_func API function
- * @ret _subsys_func Subsystem API function
- */
- #define IOAPI_INLINE( _subsys, _api_func ) \
- SINGLE_API_INLINE ( IOAPI_PREFIX_ ## _subsys, _api_func )
-
- /**
- * Provide an I/O API implementation
- *
- * @v _prefix Subsystem prefix
- * @v _api_func API function
- * @v _func Implementing function
- */
- #define PROVIDE_IOAPI( _subsys, _api_func, _func ) \
- PROVIDE_SINGLE_API ( IOAPI_PREFIX_ ## _subsys, _api_func, _func )
-
- /**
- * Provide a static inline I/O API implementation
- *
- * @v _prefix Subsystem prefix
- * @v _api_func API function
- */
- #define PROVIDE_IOAPI_INLINE( _subsys, _api_func ) \
- PROVIDE_SINGLE_API_INLINE ( IOAPI_PREFIX_ ## _subsys, _api_func )
-
- /* Include all architecture-independent I/O API headers */
- #include <gpxe/efi/efi_io.h>
-
- /* Include all architecture-dependent I/O API headers */
- #include <bits/io.h>
-
- /**
- * Wrap an I/O read
- *
- * @v _func I/O API function
- * @v _type Data type
- * @v io_addr I/O address
- * @v _prefix Prefix for address in debug message
- * @v _ndigits Number of hex digits for this data type
- */
- #define IOAPI_READ( _func, _type, io_addr, _prefix, _ndigits ) ( { \
- volatile _type *_io_addr = \
- ( ( volatile _type * ) ( intptr_t ) (io_addr) ); \
- _type _data = _func ( _io_addr ); \
- DBGIO ( "[" _prefix " %08lx] => %0" #_ndigits "llx\n", \
- io_to_bus ( _io_addr ), ( unsigned long long ) _data ); \
- _data; } )
-
- /**
- * Wrap an I/O write
- *
- * @v _func I/O API function
- * @v _type Data type
- * @v data Value to write
- * @v io_addr I/O address
- * @v _prefix Prefix for address in debug message
- * @v _ndigits Number of hex digits for this data type
- */
- #define IOAPI_WRITE( _func, _type, data, io_addr, _prefix, _ndigits ) do { \
- volatile _type *_io_addr = \
- ( ( volatile _type * ) ( intptr_t ) (io_addr) ); \
- _type _data = (data); \
- DBGIO ( "[" _prefix " %08lx] <= %0" #_ndigits "llx\n", \
- io_to_bus ( _io_addr ), ( unsigned long long ) _data ); \
- _func ( _data, _io_addr ); \
- } while ( 0 )
-
- /**
- * Wrap an I/O string read
- *
- * @v _func I/O API function
- * @v _type Data type
- * @v io_addr I/O address
- * @v data Data buffer
- * @v count Number of elements to read
- * @v _prefix Prefix for address in debug message
- * @v _ndigits Number of hex digits for this data type
- */
- #define IOAPI_READS( _func, _type, io_addr, data, count, _prefix, _ndigits ) \
- do { \
- volatile _type *_io_addr = \
- ( ( volatile _type * ) ( intptr_t ) (io_addr) ); \
- void *_data_void = (data); /* Check data is a pointer */ \
- _type * _data = ( ( _type * ) _data_void ); \
- const _type * _dbg_data = _data; \
- unsigned int _count = (count); \
- unsigned int _dbg_count = _count; \
- _func ( _io_addr, _data, _count ); \
- DBGIO ( "[" _prefix " %08lx] =>", io_to_bus ( _io_addr ) ); \
- while ( _dbg_count-- ) { \
- DBGIO ( " %0" #_ndigits "llx", \
- ( ( unsigned long long ) *(_dbg_data++) ) ); \
- } \
- DBGIO ( "\n" ); \
- } while ( 0 )
-
- /**
- * Wrap an I/O string write
- *
- * @v _func I/O API function
- * @v _type Data type
- * @v io_addr I/O address
- * @v data Data buffer
- * @v count Number of elements to write
- * @v _prefix Prefix for address in debug message
- * @v _ndigits Number of hex digits for this data type
- */
- #define IOAPI_WRITES( _func, _type, io_addr, data, count, _prefix, _ndigits ) \
- do { \
- volatile _type *_io_addr = \
- ( ( volatile _type * ) ( intptr_t ) (io_addr) ); \
- const void *_data_void = (data); /* Check data is a pointer */ \
- const _type * _data = ( ( const _type * ) _data_void ); \
- const _type * _dbg_data = _data; \
- unsigned int _count = (count); \
- unsigned int _dbg_count = _count; \
- DBGIO ( "[" _prefix " %08lx] <=", io_to_bus ( _io_addr ) ); \
- while ( _dbg_count-- ) { \
- DBGIO ( " %0" #_ndigits "llx", \
- ( ( unsigned long long ) *(_dbg_data++) ) ); \
- } \
- DBGIO ( "\n" ); \
- _func ( _io_addr, _data, _count ); \
- } while ( 0 )
-
- /**
- * Convert physical address to a bus address
- *
- * @v phys_addr Physical address
- * @ret bus_addr Bus address
- */
- unsigned long phys_to_bus ( unsigned long phys_addr );
-
- /**
- * Convert bus address to a physical address
- *
- * @v bus_addr Bus address
- * @ret phys_addr Physical address
- */
- unsigned long bus_to_phys ( unsigned long bus_addr );
-
- /**
- * Convert virtual address to a bus address
- *
- * @v addr Virtual address
- * @ret bus_addr Bus address
- */
- static inline __always_inline unsigned long
- virt_to_bus ( volatile const void *addr ) {
- return phys_to_bus ( virt_to_phys ( addr ) );
- }
-
- /**
- * Convert bus address to a virtual address
- *
- * @v bus_addr Bus address
- * @ret addr Virtual address
- *
- * This operation is not available under all memory models.
- */
- static inline __always_inline void * bus_to_virt ( unsigned long bus_addr ) {
- return phys_to_virt ( bus_to_phys ( bus_addr ) );
- }
-
- /**
- * Map bus address as an I/O address
- *
- * @v bus_addr Bus address
- * @v len Length of region
- * @ret io_addr I/O address
- */
- void * ioremap ( unsigned long bus_addr, size_t len );
-
- /**
- * Unmap I/O address
- *
- * @v io_addr I/O address
- */
- void iounmap ( volatile const void *io_addr );
-
- /**
- * Convert I/O address to bus address (for debug only)
- *
- * @v io_addr I/O address
- * @ret bus_addr Bus address
- */
- unsigned long io_to_bus ( volatile const void *io_addr );
-
- /**
- * Read byte from memory-mapped device
- *
- * @v io_addr I/O address
- * @ret data Value read
- */
- uint8_t readb ( volatile uint8_t *io_addr );
- #define readb( io_addr ) IOAPI_READ ( readb, uint8_t, io_addr, "MEM", 2 )
-
- /**
- * Read 16-bit word from memory-mapped device
- *
- * @v io_addr I/O address
- * @ret data Value read
- */
- uint16_t readw ( volatile uint16_t *io_addr );
- #define readw( io_addr ) IOAPI_READ ( readw, uint16_t, io_addr, "MEM", 4 )
-
- /**
- * Read 32-bit dword from memory-mapped device
- *
- * @v io_addr I/O address
- * @ret data Value read
- */
- uint32_t readl ( volatile uint32_t *io_addr );
- #define readl( io_addr ) IOAPI_READ ( readl, uint32_t, io_addr, "MEM", 8 )
-
- /**
- * Read 64-bit qword from memory-mapped device
- *
- * @v io_addr I/O address
- * @ret data Value read
- */
- uint64_t readq ( volatile uint64_t *io_addr );
- #define readq( io_addr ) IOAPI_READ ( readq, uint64_t, io_addr, "MEM", 16 )
-
- /**
- * Write byte to memory-mapped device
- *
- * @v data Value to write
- * @v io_addr I/O address
- */
- void writeb ( uint8_t data, volatile uint8_t *io_addr );
- #define writeb( data, io_addr ) \
- IOAPI_WRITE ( writeb, uint8_t, data, io_addr, "MEM", 2 )
-
- /**
- * Write 16-bit word to memory-mapped device
- *
- * @v data Value to write
- * @v io_addr I/O address
- */
- void writew ( uint16_t data, volatile uint16_t *io_addr );
- #define writew( data, io_addr ) \
- IOAPI_WRITE ( writew, uint16_t, data, io_addr, "MEM", 4 )
-
- /**
- * Write 32-bit dword to memory-mapped device
- *
- * @v data Value to write
- * @v io_addr I/O address
- */
- void writel ( uint32_t data, volatile uint32_t *io_addr );
- #define writel( data, io_addr ) \
- IOAPI_WRITE ( writel, uint32_t, data, io_addr, "MEM", 8 )
-
- /**
- * Write 64-bit qword to memory-mapped device
- *
- * @v data Value to write
- * @v io_addr I/O address
- */
- void writeq ( uint64_t data, volatile uint64_t *io_addr );
- #define writeq( data, io_addr ) \
- IOAPI_WRITE ( writeq, uint64_t, data, io_addr, "MEM", 16 )
-
- /**
- * Read byte from I/O-mapped device
- *
- * @v io_addr I/O address
- * @ret data Value read
- */
- uint8_t inb ( volatile uint8_t *io_addr );
- #define inb( io_addr ) IOAPI_READ ( inb, uint8_t, io_addr, "IO", 2 )
-
- /**
- * Read 16-bit word from I/O-mapped device
- *
- * @v io_addr I/O address
- * @ret data Value read
- */
- uint16_t inw ( volatile uint16_t *io_addr );
- #define inw( io_addr ) IOAPI_READ ( inw, uint16_t, io_addr, "IO", 4 )
-
- /**
- * Read 32-bit dword from I/O-mapped device
- *
- * @v io_addr I/O address
- * @ret data Value read
- */
- uint32_t inl ( volatile uint32_t *io_addr );
- #define inl( io_addr ) IOAPI_READ ( inl, uint32_t, io_addr, "IO", 8 )
-
- /**
- * Write byte to I/O-mapped device
- *
- * @v data Value to write
- * @v io_addr I/O address
- */
- void outb ( uint8_t data, volatile uint8_t *io_addr );
- #define outb( data, io_addr ) \
- IOAPI_WRITE ( outb, uint8_t, data, io_addr, "IO", 2 )
-
- /**
- * Write 16-bit word to I/O-mapped device
- *
- * @v data Value to write
- * @v io_addr I/O address
- */
- void outw ( uint16_t data, volatile uint16_t *io_addr );
- #define outw( data, io_addr ) \
- IOAPI_WRITE ( outw, uint16_t, data, io_addr, "IO", 4 )
-
- /**
- * Write 32-bit dword to I/O-mapped device
- *
- * @v data Value to write
- * @v io_addr I/O address
- */
- void outl ( uint32_t data, volatile uint32_t *io_addr );
- #define outl( data, io_addr ) \
- IOAPI_WRITE ( outl, uint32_t, data, io_addr, "IO", 8 )
-
- /**
- * Read bytes from I/O-mapped device
- *
- * @v io_addr I/O address
- * @v data Data buffer
- * @v count Number of bytes to read
- */
- void insb ( volatile uint8_t *io_addr, uint8_t *data, unsigned int count );
- #define insb( io_addr, data, count ) \
- IOAPI_READS ( insb, uint8_t, io_addr, data, count, "IO", 2 )
-
- /**
- * Read 16-bit words from I/O-mapped device
- *
- * @v io_addr I/O address
- * @v data Data buffer
- * @v count Number of words to read
- */
- void insw ( volatile uint16_t *io_addr, uint16_t *data, unsigned int count );
- #define insw( io_addr, data, count ) \
- IOAPI_READS ( insw, uint16_t, io_addr, data, count, "IO", 4 )
-
- /**
- * Read 32-bit words from I/O-mapped device
- *
- * @v io_addr I/O address
- * @v data Data buffer
- * @v count Number of words to read
- */
- void insl ( volatile uint32_t *io_addr, uint32_t *data, unsigned int count );
- #define insl( io_addr, data, count ) \
- IOAPI_READS ( insl, uint32_t, io_addr, data, count, "IO", 8 )
-
- /**
- * Write bytes to I/O-mapped device
- *
- * @v io_addr I/O address
- * @v data Data buffer
- * @v count Number of bytes to write
- */
- void outsb ( volatile uint8_t *io_addr, const uint8_t *data,
- unsigned int count );
- #define outsb( io_addr, data, count ) \
- IOAPI_WRITES ( outsb, uint8_t, io_addr, data, count, "IO", 2 )
-
- /**
- * Write 16-bit words to I/O-mapped device
- *
- * @v io_addr I/O address
- * @v data Data buffer
- * @v count Number of words to write
- */
- void outsw ( volatile uint16_t *io_addr, const uint16_t *data,
- unsigned int count );
- #define outsw( io_addr, data, count ) \
- IOAPI_WRITES ( outsw, uint16_t, io_addr, data, count, "IO", 4 )
-
- /**
- * Write 32-bit words to I/O-mapped device
- *
- * @v io_addr I/O address
- * @v data Data buffer
- * @v count Number of words to write
- */
- void outsl ( volatile uint32_t *io_addr, const uint32_t *data,
- unsigned int count );
- #define outsl( io_addr, data, count ) \
- IOAPI_WRITES ( outsl, uint32_t, io_addr, data, count, "IO", 8 )
-
- /**
- * Slow down I/O
- *
- */
- void iodelay ( void );
-
- /**
- * Read value from I/O-mapped device, slowly
- *
- * @v _func Function to use to read value
- * @v data Value to write
- * @v io_addr I/O address
- */
- #define INX_P( _func, _type, io_addr ) ( { \
- _type _data = _func ( (io_addr) ); \
- iodelay(); \
- _data; } )
-
- /**
- * Read byte from I/O-mapped device
- *
- * @v io_addr I/O address
- * @ret data Value read
- */
- #define inb_p( io_addr ) INX_P ( inb, uint8_t, io_addr )
-
- /**
- * Read 16-bit word from I/O-mapped device
- *
- * @v io_addr I/O address
- * @ret data Value read
- */
- #define inw_p( io_addr ) INX_P ( inw, uint16_t, io_addr )
-
- /**
- * Read 32-bit dword from I/O-mapped device
- *
- * @v io_addr I/O address
- * @ret data Value read
- */
- #define inl_p( io_addr ) INX_P ( inl, uint32_t, io_addr )
-
- /**
- * Write value to I/O-mapped device, slowly
- *
- * @v _func Function to use to write value
- * @v data Value to write
- * @v io_addr I/O address
- */
- #define OUTX_P( _func, data, io_addr ) do { \
- _func ( (data), (io_addr) ); \
- iodelay(); \
- } while ( 0 )
-
- /**
- * Write byte to I/O-mapped device, slowly
- *
- * @v data Value to write
- * @v io_addr I/O address
- */
- #define outb_p( data, io_addr ) OUTX_P ( outb, data, io_addr )
-
- /**
- * Write 16-bit word to I/O-mapped device, slowly
- *
- * @v data Value to write
- * @v io_addr I/O address
- */
- #define outw_p( data, io_addr ) OUTX_P ( outw, data, io_addr )
-
- /**
- * Write 32-bit dword to I/O-mapped device, slowly
- *
- * @v data Value to write
- * @v io_addr I/O address
- */
- #define outl_p( data, io_addr ) OUTX_P ( outl, data, io_addr )
-
- /**
- * Memory barrier
- *
- */
- void mb ( void );
- #define rmb() mb()
- #define wmb() mb()
-
- #endif /* _GPXE_IO_H */
|