/**
 * \file
 * \brief Essential capability definitions.
 */

/*
 * Copyright (c) 2007-2012, 2016, ETH Zurich.
 * Copyright (c) 2015, 2016 Hewlett Packard Enterprise Development LP.
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached LICENSE file.
 * If you do not find this file, copies can be found by writing to:
 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
 */

#ifndef BARRELFISH_CAPABILITIES_H
#define BARRELFISH_CAPABILITIES_H

/* FIXME: OBJBITS and OBJSIZE defines must match sizes in Hamlet's capabilities/caps.hl */

// Size of CNode entry
#define OBJBITS_CTE             6
#define OBJSIZE_CTE             (1UL << OBJBITS_CTE)
/// Number of entries in L2 CNode in bits
#define L2_CNODE_BITS           8
/// Number of entries in L2 CNode
#define L2_CNODE_SLOTS          (1UL << L2_CNODE_BITS)

#ifndef __ASSEMBLER__

#include <assert.h>
#include <stdbool.h>
#include <barrelfish_kpi/types.h>
#include <barrelfish_kpi/solution.h>

#include <aos/static_assert.h>
#include <sys/cdefs.h>

__BEGIN_DECLS

#define CAPRIGHTS_READ          (1 << 0)
#define CAPRIGHTS_WRITE         (1 << 1)
#define CAPRIGHTS_EXECUTE       (1 << 2)
#define CAPRIGHTS_GRANT         (1 << 3)
#define CAPRIGHTS_IDENTIFY      (1 << 4)
#define CAPRIGHTS_NUM           5

#define CAPRIGHTS_ALLRIGHTS     ((1 << CAPRIGHTS_NUM) - 1)
#define CAPRIGHTS_READ_WRITE    (CAPRIGHTS_READ | CAPRIGHTS_WRITE)
#define CAPRIGHTS_NORIGHTS      0

typedef uint8_t         CapRights;
#define PRIuCAPRIGHTS PRIu8
#define PRIxCAPRIGHTS PRIx8

struct dcb;

// capbits needs CapRights and dcb;
#include <barrelfish_kpi/capbits.h>

STATIC_ASSERT((L2_CNODE_SLOTS  * (1UL << OBJBITS_CTE)) == OBJSIZE_L2CNODE,
        "l2 cnode size doesn't match cte size");

static inline bool type_is_vnode(enum objtype type)
{
    STATIC_ASSERT(68 == ObjType_Num, "Check VNode definitions");

    return (type == ObjType_VNode_VTd_root_table ||
            type == ObjType_VNode_VTd_ctxt_table ||
            type == ObjType_VNode_x86_64_pml5 ||
            type == ObjType_VNode_x86_64_pml4 ||
            type == ObjType_VNode_x86_64_pdpt ||
            type == ObjType_VNode_x86_64_pdir ||
            type == ObjType_VNode_x86_64_ptable ||
            type == ObjType_VNode_x86_64_ept_pml4 ||
            type == ObjType_VNode_x86_64_ept_pdpt ||
            type == ObjType_VNode_x86_64_ept_pdir ||
            type == ObjType_VNode_x86_64_ept_ptable ||
            type == ObjType_VNode_x86_32_pdpt ||
            type == ObjType_VNode_x86_32_pdir ||
            type == ObjType_VNode_x86_32_ptable ||
            type == ObjType_VNode_AARCH64_l3 ||
            type == ObjType_VNode_AARCH64_l2 ||
            type == ObjType_VNode_AARCH64_l1 ||
            type == ObjType_VNode_AARCH64_l0 ||
            type == ObjType_VNode_ARM_l2 ||
            type == ObjType_VNode_ARM_l1
           );
}

static inline bool type_is_vroot(enum objtype type)
{
    STATIC_ASSERT(68 == ObjType_Num, "Check VNode definitions");

    return (type == ObjType_VNode_x86_64_pml4 ||
            type == ObjType_VNode_x86_64_ept_pml4 ||
#ifdef CONFIG_PAE
            type == ObjType_VNode_x86_32_pdpt ||
#else
            type == ObjType_VNode_x86_32_pdir ||
#endif
            type == ObjType_VNode_AARCH64_l0 ||
            type == ObjType_VNode_ARM_l1
           );
}
/**
 * Return size of vnode in bits. This is the size of a page table page.
 *
 * @param type Object type.
 *
 * @return Number of bits a VNode object occupies.
 */
static inline uint8_t vnode_objbits(enum objtype type)
{
    // This function should be emitted by hamlet or somesuch.
    STATIC_ASSERT(68 == ObjType_Num, "Check VNode definitions");

    if (type == ObjType_VNode_VTd_root_table ||
        type == ObjType_VNode_VTd_ctxt_table ||
        type == ObjType_VNode_x86_64_pml5 ||
        type == ObjType_VNode_x86_64_pml4 ||
        type == ObjType_VNode_x86_64_pdpt ||
        type == ObjType_VNode_x86_64_pdir ||
        type == ObjType_VNode_x86_64_ptable ||
        type == ObjType_VNode_x86_64_ept_pml4 ||
        type == ObjType_VNode_x86_64_ept_pdpt ||
        type == ObjType_VNode_x86_64_ept_pdir ||
        type == ObjType_VNode_x86_64_ept_ptable ||
        type == ObjType_VNode_x86_32_pdpt ||
        type == ObjType_VNode_x86_32_pdir ||
        type == ObjType_VNode_x86_32_ptable)
    {
        return 12;
    }
    else if (type == ObjType_VNode_AARCH64_l0 ||
             type == ObjType_VNode_AARCH64_l1 ||
             type == ObjType_VNode_AARCH64_l2 ||
             type == ObjType_VNode_AARCH64_l3)
    {
        return 12;
    }
    else if (type == ObjType_VNode_ARM_l1)
    {
        return 14;
    }
    else if (type == ObjType_VNode_ARM_l2)
    {
        return 10;
    }

    assert(0 && !"Page table size unknown.");
    return 0;
}

static inline bool type_is_ept(enum objtype type)
{
    STATIC_ASSERT(68 == ObjType_Num, "Check VNode definitions");

    return (type == ObjType_VNode_x86_64_ept_pml4 ||
            type == ObjType_VNode_x86_64_ept_pdpt ||
            type == ObjType_VNode_x86_64_ept_pdir ||
            type == ObjType_VNode_x86_64_ept_ptable);
}

/**
 * Return size of vnode in bytes. This is the size of a page table page.
 *
 * @param type Object type.
 *
 * @return Size of a VNode in bytes.
 *
 * XXX: this should probably just do 1UL << vnode_objbits(type) for vnode
 * objtypes -SG, 2016-07-06.
 */
static inline size_t vnode_objsize(enum objtype type)
{
    // This function should be emitted by hamlet or somesuch.
    STATIC_ASSERT(68 == ObjType_Num, "Check VNode definitions");

    if (type == ObjType_VNode_VTd_root_table ||
        type == ObjType_VNode_VTd_ctxt_table ||
        type == ObjType_VNode_x86_64_pml5 ||
        type == ObjType_VNode_x86_64_pml4 ||
        type == ObjType_VNode_x86_64_pdpt ||
        type == ObjType_VNode_x86_64_pdir ||
        type == ObjType_VNode_x86_64_ptable ||
        type == ObjType_VNode_x86_64_ept_pml4 ||
        type == ObjType_VNode_x86_64_ept_pdpt ||
        type == ObjType_VNode_x86_64_ept_pdir ||
        type == ObjType_VNode_x86_64_ept_ptable ||
        type == ObjType_VNode_x86_32_pdpt ||
        type == ObjType_VNode_x86_32_pdir ||
        type == ObjType_VNode_x86_32_ptable)
    {
        // XXX: cannot use BASE_PAGE_SIZE here because asmoffsets does not
        // include the right files
        return 4096; // BASE_PAGE_SIZE
    }
    else if (type == ObjType_VNode_AARCH64_l0 ||
             type == ObjType_VNode_AARCH64_l1 ||
             type == ObjType_VNode_AARCH64_l2 ||
             type == ObjType_VNode_AARCH64_l3)
    {
        return 4096;
    }
    else if (type == ObjType_VNode_ARM_l1)
    {
        // ARMv7 L1 page table is 16kB.
        return 16384;
    }
    else if (type == ObjType_VNode_ARM_l2)
    {
        return 1024;
    }

    assert(0 && !"Page table size unknown.");
    return 0;
}

/**
 * Return number of page table entries for vnode in bits.
 * @param type Object type.
 * @return Number of page table entries in bits
 */
static inline size_t vnode_entry_bits(enum objtype type) {
    // This function should be emitted by hamlet or somesuch.
    STATIC_ASSERT(68 == ObjType_Num, "Check VNode definitions");

    if (type == ObjType_VNode_VTd_root_table ||
        type == ObjType_VNode_VTd_ctxt_table ||
        type == ObjType_VNode_x86_64_pml5 ||
        type == ObjType_VNode_x86_64_pml4 ||
        type == ObjType_VNode_x86_64_pdpt ||
        type == ObjType_VNode_x86_64_pdir ||
        type == ObjType_VNode_x86_64_ptable ||
        type == ObjType_VNode_x86_64_ept_pml4 ||
        type == ObjType_VNode_x86_64_ept_pdpt ||
        type == ObjType_VNode_x86_64_ept_pdir ||
        type == ObjType_VNode_x86_64_ept_ptable)
    {
        return 9;      // log2(X86_64_PTABLE_SIZE)
    }
#ifdef CONFIG_PAE
    if (type == ObjType_VNode_x86_32_pdpt)
    {
        return 2;       // log2(X86_32_PDPTE_SIZE)
    }
    else if (type == ObjType_VNode_x86_32_pdir ||
             type == ObjType_VNode_x86_32_ptable)
    {
        return 9;       // log2(X86_32_PTABLE_SIZE) == log2(X86_32_PDIR_SIZE)
    }
#else
    if (type == ObjType_VNode_x86_32_pdir ||
        type == ObjType_VNode_x86_32_ptable)
    {
        return 10;      // log2(X86_32_PTABLE_SIZE) == log2(X86_32_PDIR_SIZE)
    }
#endif

    if (type == ObjType_VNode_AARCH64_l0 ||
        type == ObjType_VNode_AARCH64_l1 ||
        type == ObjType_VNode_AARCH64_l2 ||
        type == ObjType_VNode_AARCH64_l3)
    {
        return 9;       // log2(ARM_MAX_ENTRIES)
    }

    if (type == ObjType_VNode_ARM_l2)
    {
        return 9;       // log2(ARM_L2_MAX_ENTRIES)
    }
    else if (type == ObjType_VNode_ARM_l1)
    {
        return 12;      // log2(ARM_L1_MAX_ENTRIES)
    }

    assert(!"unknown page table type");
    return 0;
}

/**
 * Return number of slots for cnode in bits.
 * @param type Object type.
 * @return Number of page table entries in bits
 */
static inline size_t cnode_get_slots(struct capability *cnode) {
    STATIC_ASSERT(68 == ObjType_Num, "Check CNode definitions");

    switch (cnode->type) {
        case ObjType_L1CNode:
            return cnode->u.l1cnode.allocated_bytes / (1UL << OBJBITS_CTE);
        case ObjType_L2CNode:
            return L2_CNODE_SLOTS;
        default:
            assert(!"not a cnode");
            return 0;
    }
}

static inline enum objtype get_mapping_type(enum objtype captype)
{
    STATIC_ASSERT(68 == ObjType_Num, "Knowledge of all mapping types");

    switch (captype) {
        case ObjType_Frame:
            return ObjType_Frame_Mapping;
        case ObjType_EndPointUMP:
            return ObjType_EndPointUMP_Mapping;
        case ObjType_DevFrame:
            return ObjType_DevFrame_Mapping;
        case ObjType_VNode_VTd_root_table:
            return ObjType_VNode_VTd_root_table_Mapping;
        case ObjType_VNode_VTd_ctxt_table:
            return ObjType_VNode_VTd_ctxt_table_Mapping;
        case ObjType_VNode_x86_64_pml5:
            return ObjType_VNode_x86_64_pml5_Mapping;
        case ObjType_VNode_x86_64_pml4:
            return ObjType_VNode_x86_64_pml4_Mapping;
        case ObjType_VNode_x86_64_pdpt:
            return ObjType_VNode_x86_64_pdpt_Mapping;
        case ObjType_VNode_x86_64_pdir:
            return ObjType_VNode_x86_64_pdir_Mapping;
        case ObjType_VNode_x86_64_ptable:
            return ObjType_VNode_x86_64_ptable_Mapping;
        case ObjType_VNode_x86_64_ept_pml4:
            return ObjType_VNode_x86_64_ept_pml4_Mapping;
        case ObjType_VNode_x86_64_ept_pdpt:
            return ObjType_VNode_x86_64_ept_pdpt_Mapping;
        case ObjType_VNode_x86_64_ept_pdir:
            return ObjType_VNode_x86_64_ept_pdir_Mapping;
        case ObjType_VNode_x86_64_ept_ptable:
            return ObjType_VNode_x86_64_ept_ptable_Mapping;
        case ObjType_VNode_x86_32_pdpt:
            return ObjType_VNode_x86_32_pdpt_Mapping;
        case ObjType_VNode_x86_32_pdir:
            return ObjType_VNode_x86_32_pdir_Mapping;
        case ObjType_VNode_x86_32_ptable:
            return ObjType_VNode_x86_32_ptable_Mapping;
        case ObjType_VNode_ARM_l1:
            return ObjType_VNode_ARM_l1_Mapping;
        case ObjType_VNode_ARM_l2:
            return ObjType_VNode_ARM_l2_Mapping;
        case ObjType_VNode_AARCH64_l0:
            return ObjType_VNode_AARCH64_l0_Mapping;
        case ObjType_VNode_AARCH64_l1:
            return ObjType_VNode_AARCH64_l1_Mapping;
        case ObjType_VNode_AARCH64_l2:
            return ObjType_VNode_AARCH64_l2_Mapping;
        case ObjType_VNode_AARCH64_l3:
            return ObjType_VNode_AARCH64_l3_Mapping;
        /* all other types are not mappable */
        default:
            return ObjType_Null;
    }
}

static inline bool type_is_mapping(enum objtype type)
{
    STATIC_ASSERT(68 == ObjType_Num, "Knowledge of all mapping types");

    switch (type) {
        case ObjType_Frame_Mapping:
        case ObjType_EndPointUMP_Mapping:
        case ObjType_DevFrame_Mapping:
        case ObjType_VNode_VTd_root_table_Mapping:
        case ObjType_VNode_VTd_ctxt_table_Mapping:
        case ObjType_VNode_x86_64_pml5_Mapping:
        case ObjType_VNode_x86_64_pml4_Mapping:
        case ObjType_VNode_x86_64_pdpt_Mapping:
        case ObjType_VNode_x86_64_pdir_Mapping:
        case ObjType_VNode_x86_64_ptable_Mapping:
        case ObjType_VNode_x86_64_ept_pml4_Mapping:
        case ObjType_VNode_x86_64_ept_pdpt_Mapping:
        case ObjType_VNode_x86_64_ept_pdir_Mapping:
        case ObjType_VNode_x86_64_ept_ptable_Mapping:
        case ObjType_VNode_x86_32_pdpt_Mapping:
        case ObjType_VNode_x86_32_pdir_Mapping:
        case ObjType_VNode_x86_32_ptable_Mapping:
        case ObjType_VNode_ARM_l1_Mapping:
        case ObjType_VNode_ARM_l2_Mapping:
        case ObjType_VNode_AARCH64_l0_Mapping:
        case ObjType_VNode_AARCH64_l1_Mapping:
        case ObjType_VNode_AARCH64_l2_Mapping:
        case ObjType_VNode_AARCH64_l3_Mapping:
            return true;

        /* all other types are not mapping types */
        default:
            return false;
    }
}

static inline bool type_is_mappable(enum objtype type)
{
    STATIC_ASSERT(68 == ObjType_Num, "Knowledge of all mappable types");

    switch (type) {
        case ObjType_Frame:
        case ObjType_EndPointUMP:
        case ObjType_DevFrame:
        case ObjType_VNode_VTd_root_table:
        case ObjType_VNode_VTd_ctxt_table:
        case ObjType_VNode_x86_64_pml5:
        case ObjType_VNode_x86_64_pml4:
        case ObjType_VNode_x86_64_pdpt:
        case ObjType_VNode_x86_64_pdir:
        case ObjType_VNode_x86_64_ptable:
        case ObjType_VNode_x86_32_pdpt:
        case ObjType_VNode_x86_32_pdir:
        case ObjType_VNode_x86_32_ptable:
        case ObjType_VNode_ARM_l1:
        case ObjType_VNode_ARM_l2:
        case ObjType_VNode_AARCH64_l0:
        case ObjType_VNode_AARCH64_l1:
        case ObjType_VNode_AARCH64_l2:
        case ObjType_VNode_AARCH64_l3:
            return true;

        /* all other types are not mappable */
        default:
            return false;
    }
}

/* XXX: this should be generated by hamlet. */
static inline pasid_t get_pasid(struct capability *cap)
{
    STATIC_ASSERT(68 == ObjType_Num, "Knowledge of all types that have a pasid");

    if (!type_is_mappable(cap->type)) {
        return -1;
    }

    // XXX: this assumes that everything that's mappable is derived from the
    // abstract capability type Memory.
    return cap->u.frame.pasid;
}

/**
 * CNode capability commands.
 */
enum cnode_cmd {
    CNodeCmd_Copy,      ///< Copy capability
    CNodeCmd_Mint,      ///< Mint capability
    CNodeCmd_Retype,    ///< Retype capability
    CNodeCmd_Delete,    ///< Delete capability
    CNodeCmd_Revoke,    ///< Revoke capability
    CNodeCmd_Create,    ///< Create capability
    CNodeCmd_GetState,  ///< Get distcap state for capability
    CNodeCmd_GetSize,   ///< Get Size of CNode, only applicable for L1 Cnode
    CNodeCmd_Resize,    ///< Resize CNode, only applicable for L1 Cnode
    CNodeCmd_CapIdentify ///< Identify capability
};

enum vnode_cmd {
    VNodeCmd_Map,
    VNodeCmd_Unmap,
    VNodeCmd_ModifyFlags,
    VNodeCmd_CleanDirtyBits, ///< Cleans all dirty bit in the table
    VNodeCmd_CopyRemap,      ///< Copy and remap page table for copy-on-write
    VNodeCmd_Inherit,        ///< Clone page table
};

/**
 * Mapping commands
 */
enum mapping_cmd {
    MappingCmd_Modify,
    MappingCmd_Destroy,
};

/**
 * Kernel capabilities commands.
 * Monitor's invocations of capability operations
 * which the kernel will not subject to cross core checks
 */
enum kernel_cmd {
    KernelCmd_Spawn_core,         ///< Spawn a new kernel
    KernelCmd_Identify_cap,       ///< Return the meta data of a capability
    KernelCmd_Identify_domains_cap, ///< Return the meta data of another domain's capability
    KernelCmd_Remote_relations,   ///< Set capability as being remote
    KernelCmd_Cap_has_relations,      ///< Return presence of local relations
    KernelCmd_Create_cap,         ///< Create a new capability
    KernelCmd_Copy_existing,
    KernelCmd_Get_core_id,        ///< Returns the id of the core the domain is on
    KernelCmd_Get_arch_id,        ///< Returns arch id of caller's core
    KernelCmd_Nullify_cap,        ///< Set the capability to NULL allowed it to be reused
    KernelCmd_Setup_trace,        ///< Set up trace buffer
    KernelCmd_Register,           ///< Register monitor notify endpoint
    KernelCmd_Domain_Id,          ///< Set domain ID of dispatcher
    KernelCmd_Get_cap_owner,
    KernelCmd_Set_cap_owner,
    KernelCmd_Lock_cap,
    KernelCmd_Unlock_cap,
    KernelCmd_Delete_last,
    KernelCmd_Delete_foreigns,
    KernelCmd_Revoke_mark_target,
    KernelCmd_Revoke_mark_relations,
    KernelCmd_Delete_step,
    KernelCmd_Clear_step,
    KernelCmd_Retype,
    KernelCmd_Has_descendants,
    KernelCmd_Is_retypeable,
    KernelCmd_Sync_timer,
    KernelCmd_IPI_Register,
    KernelCmd_IPI_Delete,
    KernelCmd_GetGlobalPhys,
    KernelCmd_Add_kcb,            ///< add extra kcb to be scheduled
    KernelCmd_Remove_kcb,         ///< remove kcb from scheduling ring
    KernelCmd_Suspend_kcb_sched,  ///< suspend/resume kcb scheduler
    KernelCmd_Get_platform,       ///< Get architecture platform
    KernelCmd_ReclaimRAM,         ///< Retrieve stored ram caps from KCB
    KernelCmd_Count
};

/**
 * Specific commands for dispatcher capabilities.
 */
enum dispatcher_cmd {
    DispatcherCmd_Setup,            ///< Set dispatcher parameters
    DispatcherCmd_Properties,       ///< Set dispatcher properties
    DispatcherCmd_PerfMon,          ///< Performance monitoring
    DispatcherCmd_SetupGuest,       ///< Set up the DCB of a guest domain
    DispatcherCmd_DumpPTables,      ///< Dump hw page tables of dispatcher
    DispatcherCmd_DumpCapabilities, ///< Dump capabilities of dispatcher
    DispatcherCmd_Vmread,           ///< Execute vmread on the current and active VMCS
    DispatcherCmd_Vmwrite,          ///< Execute vmwrite on the current and active VMCS
    DispatcherCmd_Vmptrld,          ///< Make VMCS clear and inactive
    DispatcherCmd_Vmclear,          ///< Make VMCS current and active
};

/**
 * Kernel control block commands.
 */
enum kcb_cmd {
    KCBCmd_Identify,      ///< Return base address of KCB frame
    KCBCmd_Clone,         ///< Duplicate core_data
};

/**
 * RAM capability commands
 */
enum ram_cmd {
    RAMCmd_Noop,          ///< Noop invocation for benchmark
};

/**
 * IRQ Table capability commands.
 */
enum irqtable_cmd {
    IRQTableCmd_Alloc,  ///< Allocate new vector (XXX: HACK: this is x86 specific)
    IRQTableCmd_AllocDestCap,  ///< Allocate new dest capability (XXX: HACK: this is x86 specific)
    IRQTableCmd_Set,    ///< Set endpoint for IRQ# notifications
    IRQTableCmd_Delete  ///< Remove notification endpoint for IRQ#
};

/**
 * IRQ Vector commands.
 */

enum irqdest_cmd {
	IRQDestCmd_Connect,	///< Connect this capability to a messaging channel
	IRQDestCmd_GetVector, ///< Return the local interrupt vector
	IRQDestCmd_GetCpu ///< Return the local interrupt vector
};

/**
 * IRQ Vector commands.
 */

enum irqsrc_cmd {
    IRQSrcCmd_GetVecStart,   ///< Return vector range start
    IRQSrcCmd_GetVecEnd   ///< Return vector range high
};


/**
 * IO capability commands.
 */
enum io_cmd {
    IOCmd_Outb,         ///< Output byte to port
    IOCmd_Outw,         ///< Output word to port
    IOCmd_Outd,         ///< Output double word to port
    IOCmd_Inb,          ///< Input byte from port
    IOCmd_Inw,          ///< Input word from port
    IOCmd_Ind           ///< Input double word from port
};

/**
 * DeviceID Manager Commands
 */

enum devidman_cmd {
    DeviceIDManager_CreateID,   ///< Create a new DeviceID
};


/**
 * Notify capability commands.
 */
enum notify_cmd {
    NotifyCmd_Send
};


/**
 * Performance monitoring commands.
 * Seems to be already included in the Dispatcher capability.
 */
enum perfmon_cmd {
    PerfmonCmd_Activate,    ///< Activate performance counters
    PerfmonCmd_Deactivate,  ///< Deactivate performance counters
    PerfmonCmd_Write        ///< Read current performance counter values
};


/**
 * ID capability commands.
 */
enum id_cmd {
    IDCmd_Identify  ///< Return system-wide unique ID
};

/**
 * IPI capability commands
 */

enum ipi_cmd {
    IPICmd_Send_Start,     ///< Send Startup IPI to a destination core
    IPICmd_Send_Init,      ///< Send Init IPI to a destination core
};

/**
 * Maximum command ordinal.
 */
#define CAP_MAX_CMD KernelCmd_Count

/**
 * \brief Values returned from frame identify invocation
 */
struct frame_identity {
    genpaddr_t base;   ///< Physical base address of frame
    gensize_t  bytes;  ///< Size of frame, in bytes
    pasid_t    pasid;  ///< the address space id
};

/**
 * \brief Values returned from the VNode identify invocation
 */
struct vnode_identity {
    genpaddr_t base;   ///< Physical base address of the VNode
    uint8_t type;      ///< Type of VNode
};

/**
 * @brief values for the type field in the device_identity struct below
 */
typedef enum {
    DEVICE_ID_TYPE_UNKNOWN = 0,
    DEVICE_ID_TYPE_PCI     = 1,
    DEVICE_ID_TYPE_USB     = 2,
    DEVICE_ID_TYPE_MAX     = 3,
} device_id_type_t;

/**
 * \brief Values returned from the DeviceID identify invocation
 */
struct device_identity {
    uint16_t segment;
    uint8_t  bus;
    uint8_t  device;
    uint8_t  function;
    uint8_t  type;
    uint16_t flags;
};


struct endpoint_identity {
    genpaddr_t base;   ///< Physical Address of the Endpoint
    gensize_t  length; ///< Length of the Endpoint
    uint16_t   iftype; ///< interface type
    uint16_t   eptype; ///< type of the endpoint
};

__END_DECLS

#endif // __ASSEMBLER__

#endif // BARRELFISH_CAPABILITIES_H
