#ifndef _LINK_H
#define _LINK_H

/*++

Copyright (c) 1998  Intel Corporation

Module Name:

    link.h

Abstract:

    EFI link list macro's



Revision History

--*/

#ifndef EFI_NT_EMUL

/* 
 *  List entry - doubly linked list
 */

typedef struct _LIST_ENTRY {
    struct _LIST_ENTRY  *Flink;
    struct _LIST_ENTRY  *Blink;
} LIST_ENTRY;

#endif 


/* 
 *   VOID
 *   InitializeListHead(
 *       LIST_ENTRY *ListHead
 *       );
 */

#define InitializeListHead(ListHead) \
    (ListHead)->Flink = ListHead;    \
    (ListHead)->Blink = ListHead;

/* 
 *   BOOLEAN
 *   IsListEmpty(
 *       PLIST_ENTRY ListHead
 *       );
 */

#define IsListEmpty(ListHead) \
    ((ListHead)->Flink == (ListHead))

/* 
 *   VOID
 *   RemoveEntryList(
 *       PLIST_ENTRY Entry
 *       );
 */

#define _RemoveEntryList(Entry) {       \
        LIST_ENTRY *_Blink, *_Flink;    \
        _Flink = (Entry)->Flink;        \
        _Blink = (Entry)->Blink;        \
        _Blink->Flink = _Flink;         \
        _Flink->Blink = _Blink;         \
        }

#if EFI_DEBUG
    #define RemoveEntryList(Entry)                      \
        _RemoveEntryList(Entry);                        \
        (Entry)->Flink = (LIST_ENTRY *) BAD_POINTER;    \
        (Entry)->Blink = (LIST_ENTRY *) BAD_POINTER; 
#else
    #define RemoveEntryList(Entry)      \
        _RemoveEntryList(Entry);
#endif

/* 
 *   VOID
 *   InsertTailList(
 *       PLIST_ENTRY ListHead,
 *       PLIST_ENTRY Entry
 *       );
 */

#define InsertTailList(ListHead,Entry) {\
    LIST_ENTRY *_ListHead, *_Blink;     \
    _ListHead = (ListHead);             \
    _Blink = _ListHead->Blink;          \
    (Entry)->Flink = _ListHead;         \
    (Entry)->Blink = _Blink;            \
    _Blink->Flink = (Entry);            \
    _ListHead->Blink = (Entry);         \
    }

/* 
 *   VOID
 *   InsertHeadList(
 *       PLIST_ENTRY ListHead,
 *       PLIST_ENTRY Entry
 *       );
 */

#define InsertHeadList(ListHead,Entry) {\
    LIST_ENTRY *_ListHead, *_Flink;     \
    _ListHead = (ListHead);             \
    _Flink = _ListHead->Flink;          \
    (Entry)->Flink = _Flink;            \
    (Entry)->Blink = _ListHead;         \
    _Flink->Blink = (Entry);            \
    _ListHead->Flink = (Entry);         \
    }

/* 
 *   EFI_FIELD_OFFSET - returns the byte offset to a field within a structure
 */

#define EFI_FIELD_OFFSET(TYPE,Field) ((UINTN)(&(((TYPE *) 0)->Field)))

/* 
 *   CONTAINING_RECORD - returns a pointer to the structure
 *       from one of it's elements.
 */

#define _CR(Record, TYPE, Field)  \
    ((TYPE *) ( (CHAR8 *)(Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))

#if EFI_DEBUG
    #define CR(Record, TYPE, Field, Sig)     \
        _CR(Record, TYPE, Field)->Signature != Sig ?        \
            (TYPE *) ASSERT_STRUCT(_CR(Record, TYPE, Field), Record) : \
            _CR(Record, TYPE, Field)
#else
    #define CR(Record, TYPE, Field, Signature)   \
        _CR(Record, TYPE, Field)                           
#endif


/* 
 *  A lock structure
 */

typedef struct _FLOCK {
    EFI_TPL     Tpl;
    EFI_TPL     OwnerTpl;
    UINTN       Lock;
} FLOCK;

#endif
