freeNOS代码走读杂记

最近在看github上一个微os的代码,freeNOS.走读的过程中顺便记一下学习的点

枚举用位偏移定义来提高效率

/**
 * Memory access flags.
 */
typedef enum Access
{
    None        = 0,
    Readable    = 1 << 0,
    Writable    = 1 << 1,
    Executable  = 1 << 2,
    User        = 1 << 3,
    Uncached    = 1 << 4,
    InnerCached = 1 << 5,
    OuterCached = 1 << 6,
    Device      = 1 << 7
}

读,写是通过port口地址加offset值来定位具体内存地址,再进行具体的内存操作

为了提高效率所有的IO操作函数全部都是inline

//IntelIO.h
inline u8 inb(u16 port)
{
    u8 b;
    port += m_base;
    asm volatile ("inb %%dx, %%al" : "=a" (b) : "d" (port));
    return b;
}

/**
 * Read a word from a port.
 * @param port The I/O port to read from.
 * @return Word read from the port.
 */
inline u16 inw(u16 port)
{
    u16 w;
    port += m_base;
    asm volatile ("inw %%dx, %%ax" : "=a" (w) : "d" (port));
    return w;
}

/**
 * Output a byte to a port.
 * @param port Port to write to.
 * @param byte The byte to output.
 */
inline void outb(u16 port, u8 byte)
{
    port += m_base;
    asm volatile ("outb %%al,%%dx"::"a" (byte),"d" (port));
}

/**
 * Output a word to a port.
 * @param port Port to write to.
 * @param byte The word to output.
 */
inline void outw(u16 port, u16 word)
{
    port += m_base;
    asm volatile ("outw %%ax,%%dx"::"a" (word),"d" (port));
}

/**
 * Output a long to a I/O port.
 * @param port Target I/O port.
 * @param l The long 32-bit number to output.
 */
inline void outl(u16 port, u32 l)
{
    port += m_base;
    asm volatile ("outl %%eax,%%dx"::"a" (l),"d" (port));
}

/**
 * Read memory mapped register.
 *
 * @param addr Address of the register to read.
 * @return 32-bit value of the register.
 */
inline u32 read(Address addr)
{
    addr += m_base;
    return *(volatile u32 *) addr;
}

/**
 * Read a number of 32-bit values.
 *
 * @param addr Address of the starting 32-bit value.
 * @param count Number of bytes to read.
 * @param buf Output buffer.
 */
inline void read(Address addr, Size count, void *buf)
{
    for (Size i = 0; i < count; i+= sizeof(u32))
    {
        *(u32 *)(((u8 *)buf) + i) = read(addr + i);
    }
}

/**
 * Write memory mapped register.
 *
 * @param addr Address of the register to write.
 * @param data 32-bit value to write in the register.
 */
inline void write(Address addr, u32 data)
{
    addr += m_base;
    *(volatile u32 *) addr = data;
}

寄存器对应bit置1 set()和置0 unset():

/**
 * Set bits in memory mapped register.
 *
 * @param addr Address of the register to write.
 * @param data 32-bit value containing the bits to set (bitwise or).
 */
inline void set(Address addr, u32 data)
{
    u32 current = read(addr);
    current |= data;
    write(addr, current);
}

/**
 * Unset bits in memory mapped register.
 *
 * @param addr Address of the register to write.
 * @param data 32-bit value containing the bits to set (bitwise or).
 */
inline void unset(Address addr, u32 data)
{
    u32 current = read(addr);
    current &= ~(data);
    write(addr, current);
}

地址等关键变量类型通过typedef来定义,提高可读性和健壮性。大量采用了switch-case操作,基本没有if判断操作,通过state去串联(状态机?)。
函数返回值只返回当前操作的状态,其他逻辑信息全部用出参表示。
函数内基本没有任何合法性判断和异常处理流程代码。

猜你喜欢

转载自blog.csdn.net/toyijiu/article/details/82682887