API: Add a generic API for port and mem mapped registers functions

sys_io.h header file declares the generic API for such operations. It
properly separates port and memory mapped registers, with declaring
respective types: io_port_t and mm_reg_t.

Memory mapped registers are the most common type of registers drivers
will play with. Thus providing generic sys_readX/sys_writeX functions in
sys_io.h. Those are defined as inline as they are really simple.

Ports are mostly (always?) found in x86 architecture.
Currently no ARM or ARC header file propose any implementation of
those. If really necessary (a cross-architecture driver using
sys_in/sys_out functions), those architecture will provide the proper
implementation or at least a macro gluing those towards
sys_read/sys_write.

Change-Id: If77590d4bcefcdfa6aa181a88ced342f8565d5b8
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
Tomasz Bursztyka 2015-08-21 12:49:57 +03:00 committed by Anas Nashif
commit c6d0bea109
2 changed files with 269 additions and 87 deletions

View file

@ -40,6 +40,8 @@
* Include nanokernel/cpu.h instead
*/
#include <sys_io.h>
#ifndef _ASMLANGUAGE
#include <stdint.h>
#include <stddef.h>
@ -246,127 +248,124 @@ static inline __attribute__((always_inline))
}
/**
*
* @brief Output a byte to an IA-32 I/O port
*
* This function issues the 'out' instruction to write a byte to the specified
* I/O port.
*
* @return N/A
*
* NOMANUAL
*/
/* Implementation of sys_io.h's documented functions */
static inline __attribute__((always_inline))
void sys_out8(unsigned char data, unsigned int port)
void sys_out8(uint8_t data, io_port_t port)
{
__asm__ volatile("outb %%al, %%dx;\n\t" : : "a"(data), "d"(port));
}
/**
*
* @brief Input a byte from an IA-32 I/O port
*
* This function issues the 'in' instruction to read a byte from the specified
* I/O port.
*
* @return the byte read from the specified I/O port
*
* NOMANUAL
*/
static inline __attribute__((always_inline))
unsigned char sys_in8(unsigned int port)
uint8_t sys_in8(io_port_t port)
{
char retByte;
uint8_t ret;
__asm__ volatile("inb %%dx, %%al;\n\t" : "=a"(retByte) : "d"(port));
return retByte;
__asm__ volatile("inb %%dx, %%al;\n\t" : "=a"(ret) : "d"(port));
return ret;
}
/**
*
* @brief Output a word to an IA-32 I/O port
*
* This function issues the 'out' instruction to write a word to the
* specified I/O port.
*
* @return N/A
*
* NOMANUAL
*/
static inline __attribute__((always_inline))
void sys_out16(unsigned short data, unsigned int port)
void sys_out16(uint16_t data, io_port_t port)
{
__asm__ volatile("outw %%ax, %%dx;\n\t" : : "a"(data), "d"(port));
}
/**
*
* @brief Input a word from an IA-32 I/O port
*
* This function issues the 'in' instruction to read a word from the
* specified I/O port.
*
* @return the word read from the specified I/O port
*
* NOMANUAL
*/
static inline __attribute__((always_inline))
unsigned short sys_in16(unsigned int port)
static inline inline __attribute__((always_inline))
uint16_t sys_in16(io_port_t port)
{
unsigned short retWord;
uint16_t ret;
__asm__ volatile("inw %%dx, %%ax;\n\t" : "=a"(retWord) : "d"(port));
return retWord;
__asm__ volatile("inw %%dx, %%ax;\n\t" : "=a"(ret) : "d"(port));
return ret;
}
/**
*
* @brief Output a long word to an IA-32 I/O port
*
* This function issues the 'out' instruction to write a long word to the
* specified I/O port.
*
* @return N/A
*
* NOMANUAL
*/
static inline __attribute__((always_inline))
void sys_out32(unsigned int data, unsigned int port)
void sys_out32(uint32_t data, io_port_t port)
{
__asm__ volatile("outl %%eax, %%dx;\n\t" : : "a"(data), "d"(port));
}
/**
*
* @brief Input a long word from an IA-32 I/O port
*
* This function issues the 'in' instruction to read a long word from the
* specified I/O port.
*
* @return the long read from the specified I/O port
*
* NOMANUAL
*/
static inline inline __attribute__((always_inline))
uint32_t sys_in32(io_port_t port)
{
uint32_t ret;
__asm__ volatile("inl %%dx, %%eax;\n\t" : "=a"(ret) : "d"(port));
return ret;
}
static inline inline __attribute__((always_inline))
void sys_write8(uint8_t data, mm_reg_t addr)
{
__asm__ volatile("movb %0, %1;\n\t"
:
: "q"(data), "m" (*(volatile uint8_t *) addr)
: "memory");
}
static inline inline __attribute__((always_inline))
uint8_t sys_read8(mm_reg_t addr)
{
uint8_t ret;
__asm__ volatile("movb %1, %0;\n\t"
: "=q"(ret)
: "m" (*(volatile uint8_t *) addr)
: "memory");
return ret;
}
static inline __attribute__((always_inline))
unsigned long sys_in32(unsigned int port)
void sys_write16(uint16_t data, mm_reg_t addr)
{
unsigned long retLong;
__asm__ volatile("inl %%dx, %%eax;\n\t" : "=a"(retLong) : "d"(port));
return retLong;
__asm__ volatile("movw %0, %1;\n\t"
:
: "r"(data), "m" (*(volatile uint16_t *) addr)
: "memory");
}
static inline inline __attribute__((always_inline))
uint16_t sys_read16(mm_reg_t addr)
{
uint16_t ret;
__asm__ volatile("movw %1, %0;\n\t"
: "=r"(ret)
: "m" (*(volatile uint16_t *) addr)
: "memory");
return ret;
}
static inline inline __attribute__((always_inline))
void sys_write32(uint32_t data, mm_reg_t addr)
{
__asm__ volatile("movl %0, %1;\n\t"
:
: "r"(data), "m" (*(volatile uint32_t *) addr)
: "memory");
}
static inline __attribute__((always_inline))
uint32_t sys_read32(mm_reg_t addr)
{
uint32_t ret;
__asm__ volatile("movl %1, %0;\n\t"
: "=r"(ret)
: "m" (*(volatile uint32_t *) addr)
: "memory");
return ret;
}
#endif /* _ASMLANGUAGE */
#endif /* _ASM_INLINE_GCC_PUBLIC_GCC_H */

183
include/sys_io.h Normal file
View file

@ -0,0 +1,183 @@
/* Port and memory mapped registers I/O operations */
/*
* Copyright (c) 2015 Intel Corporation.
*
* Redistribution and use in source and binary froms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary from must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3) Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __SYS_IO_H__
#define __SYS_IO_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
typedef uint32_t io_port_t;
typedef uint32_t mm_reg_t;
/* Port I/O functions */
/**
* @fn static inline void sys_out8(uint8_t data, io_port_t port);
* @brief Output a byte to an I/O port
*
* This function writes a byte to the given port.
*
* @param data the byte to write
* @param port the port address where to write the byte
*/
/**
* @fn static inline uint8_t sys_in8(io_port_t port);
* @brief Input a byte from an I/O port
*
* This function reads a byte from the port.
*
* @param port the port address from where to read the byte
*
* @return the byte read
*/
/**
* @fn static inline void sys_out16(uint16_t data, io_port_t port);
* @brief Output a 16 bits to an I/O port
*
* This function writes a 16 bits to the given port.
*
* @param data the 16 bits to write
* @param port the port address where to write the 16 bits
*/
/**
* @fn static inline uint16_t sys_in16(io_port_t port);
* @brief Input 16 bits from an I/O port
*
* This function reads 16 bits from the port.
*
* @param port the port address from where to read the 16 bits
*
* @return the 16 bits read
*/
/**
* @fn static inline void sys_out32(uint32_t data, io_port_t port);
* @brief Output 32 bits to an I/O port
*
* This function writes 32 bits to the given port.
*
* @param data the 32 bits to write
* @param port the port address where to write the 32 bits
*/
/**
* @fn static inline uint32_t sys_in32(io_port_t port);
* @brief Input 32 bits from an I/O port
*
* This function reads 32 bits from the port.
*
* @param port the port address from where to read the 32 bits
*
* @return the 32 bits read
*/
/* Memory mapped registers I/O functions */
/**
* @fn static inline void sys_write8(uint8_t data, mm_reg_t addr);
* @brief Write a byte to a memory mapped register
*
* This function writes a byte to the given memory mapped register.
*
* @param data the byte to write
* @param addr the memory mapped register address where to write the byte
*/
/**
* @fn static inline uint8_t sys_read8(mm_reg_t addr);
* @brief Read a byte from a memory mapped register
*
* This function reads a byte from the given memory mapped register.
*
* @param addr the memory mapped register address from where to read the byte
*
* @return the byte read
*/
/**
* @fn static inline void sys_write16(uint16_t data, mm_reg_t addr);
* @brief Write 16 bits to a memory mapped register
*
* This function writes 16 bits to the given memory mapped register.
*
* @param data the 16 bits to write
* @param addr the memory mapped register address where to write the 16 bits
*/
/**
* @fn static inline uint16_t sys_read16(mm_reg_t addr);
* @brief Read 16 bits from a memory mapped register
*
* This function reads 16 bits from the given memory mapped register.
*
* @param addr the memory mapped register address from where to read
* the 16 bits
*
* @return the 16 bits read
*/
/**
* @fn static inline void sys_write32(uint32_t data, mm_reg_t addr);
* @brief Write 32 bits to a memory mapped register
*
* This function writes 32 bits to the given memory mapped register.
*
* @param data the 32 bits to write
* @param addr the memory mapped register address where to write the 32 bits
*/
/**
* @fn static inline uint32_t sys_read32(mm_reg_t addr);
* @brief Read 32 bits from a memory mapped register
*
* This function reads 32 bits from the given memory mapped register.
*
* @param addr the memory mapped register address from where to read
* the 32 bits
*
* @return the 32 bits read
*/
#ifdef __cplusplus
}
#endif
#endif /* __SYS_IO_H__ */