/* Copyright (c) 2015 Broadcom Corporation All Rights Reserved <:label-BRCM:2015:DUAL/GPL:standard This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation (the "GPL"). This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php, or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. :> */ #include "phy_mac_sec.h" /*---------------------------------------------------------------------------- * Definitions and macros */ typedef struct { /* macsec_List head */ List_Element_t * Head_p; /* macsec_List tail */ List_Element_t * Tail_p; /* Number of elements in the list */ uint32_t ElementCount; } List_t; /*---------------------------------------------------------------------------- * Local variables */ /* Statically allocated list instances. This will be deprecated in future. */ static List_t macsec_List[6]; /*---------------------------------------------------------------------------- * macsec_List_Init * */ List_Status_t macsec_List_Init(const uint32_t ListID, void * const ListInstance_p) { List_t * List_p; if (ListInstance_p) List_p = (List_t*)ListInstance_p; else List_p = &macsec_List[ListID]; List_p->ElementCount = 0; List_p->Head_p = NULL; List_p->Tail_p = NULL; return LIST_STATUS_OK; } /*---------------------------------------------------------------------------- * macsec_List_AddToHead * */ List_Status_t macsec_List_AddToHead(const uint32_t ListID, void * const ListInstance_p, List_Element_t * const Element_p) { List_Element_t * TempElement_p; List_t * List_p; if (ListInstance_p) List_p = (List_t*)ListInstance_p; else List_p = &macsec_List[ListID]; TempElement_p = List_p->Head_p; List_p->Head_p = Element_p; /* Previous element in the list, this is a head */ Element_p->Internal[0] = NULL; /* Next element in the list */ Element_p->Internal[1] = TempElement_p; /* Check if this is the first element */ if (List_p->ElementCount == 0) List_p->Tail_p = List_p->Head_p; else /* Link the old head to the new head */ TempElement_p->Internal[0] = Element_p; List_p->ElementCount++; return LIST_STATUS_OK; } /*---------------------------------------------------------------------------- * macsec_List_RemoveFromTail * */ List_Status_t macsec_List_RemoveFromTail(const uint32_t ListID, void * const ListInstance_p, List_Element_t ** const Element_pp) { List_Element_t * TempElement_p; List_t * List_p; if (ListInstance_p) List_p = (List_t*)ListInstance_p; else List_p = &macsec_List[ListID]; if (List_p->ElementCount == 0) return LIST_ERROR_BAD_ARGUMENT; /* Get the previous for the tail element in the list */ TempElement_p = (List_Element_t*)List_p->Tail_p->Internal[0]; List_p->Tail_p->Internal[0] = NULL; List_p->Tail_p->Internal[1] = NULL; *Element_pp = List_p->Tail_p; /* Set the new tail */ List_p->Tail_p = TempElement_p; /* Check if this is the last element */ if (List_p->ElementCount == 1) List_p->Head_p = NULL; else /* New tail must have no next element */ List_p->Tail_p->Internal[1] = NULL; List_p->ElementCount--; return LIST_STATUS_OK; } /*---------------------------------------------------------------------------- * macsec_List_RemoveAnywhere */ List_Status_t macsec_List_RemoveAnywhere(const uint32_t ListID, void * const ListInstance_p, List_Element_t * const Element_p) { List_Element_t * PrevElement_p, * NextElement_p; List_t * List_p; if (ListInstance_p) List_p = (List_t*)ListInstance_p; else List_p = &macsec_List[ListID]; if (List_p->ElementCount == 0) return LIST_ERROR_BAD_ARGUMENT; /* Check element belongs to this list */ { uint32_t i; List_Element_t * TempElement_p = List_p->Head_p; for (i = 0; i < List_p->ElementCount; i++) { List_Element_t * p; if (TempElement_p == Element_p) break; /* Found */ p = TempElement_p->Internal[1]; if (p) TempElement_p = p; /* not end of list yet */ else return LIST_ERROR_BAD_ARGUMENT; /* Not found */ } if (TempElement_p != Element_p) return LIST_ERROR_BAD_ARGUMENT; /* Not found */ } PrevElement_p = Element_p->Internal[0]; NextElement_p = Element_p->Internal[1]; Element_p->Internal[0] = NULL; Element_p->Internal[1] = NULL; if (PrevElement_p) PrevElement_p->Internal[1] = NextElement_p; else List_p->Head_p = NextElement_p; if (NextElement_p) NextElement_p->Internal[0] = PrevElement_p; else List_p->Tail_p = NULL; List_p->ElementCount--; return LIST_STATUS_OK; } /*---------------------------------------------------------------------------- * macsec_List_GetListElementCount * */ List_Status_t macsec_List_GetListElementCount(const uint32_t ListID, void * const ListInstance_p, uint32_t * const Count_p) { if (Count_p == NULL) return LIST_ERROR_BAD_ARGUMENT; { List_t * List_p; if (ListInstance_p) List_p = (List_t*)ListInstance_p; else List_p = &macsec_List[ListID]; *Count_p = List_p->ElementCount; } return LIST_STATUS_OK; } /*---------------------------------------------------------------------------- * macsec_List_RemoveFromHead * */ List_Status_t macsec_List_RemoveFromHead(const uint32_t ListID, void * const ListInstance_p, List_Element_t ** const Element_pp) { List_t * List_p; if (ListInstance_p) List_p = (List_t*)ListInstance_p; else List_p = &macsec_List[ListID]; if (Element_pp == NULL) return LIST_ERROR_BAD_ARGUMENT; if (List_p->ElementCount == 0) return LIST_ERROR_BAD_ARGUMENT; /* Remove the element from the list head */ { List_Element_t * TempElement_p; /* Get the next for the head element in the list */ TempElement_p = (List_Element_t*)List_p->Head_p->Internal[1]; List_p->Head_p->Internal[0] = NULL; List_p->Head_p->Internal[1] = NULL; *Element_pp = List_p->Head_p; List_p->Head_p = TempElement_p; /* Check if this is the last element */ if (List_p->ElementCount == 1) List_p->Tail_p = NULL; else List_p->Head_p->Internal[0] = NULL; List_p->ElementCount--; } return LIST_STATUS_OK; } /*---------------------------------------------------------------------------- * macsec_List_GetHead */ List_Status_t macsec_List_GetHead(const uint32_t ListID, void * const ListInstance_p, const List_Element_t ** const Element_pp) { if (Element_pp == NULL) return LIST_ERROR_BAD_ARGUMENT; /* Get the list head */ { List_t * List_p; if (ListInstance_p) List_p = (List_t*)ListInstance_p; else List_p = &macsec_List[ListID]; *Element_pp = List_p->Head_p; } return LIST_STATUS_OK; } /*---------------------------------------------------------------------------- * macsec_List_GetInstanceByteCount * * Gets the memory size of the list instance (in bytes) excluding the list * elements memory size. This list memory size can be used to allocate a list * instance and pass a pointer to it subsequently to the List_*() functions. * * This function is re-entrant and can be called any time. * * Return Values * Size of the list administration memory in bytes. */ uint32_t macsec_List_GetInstanceByteCount(void) { return sizeof(List_t); } List_Element_t * macsec_List_GetNextElement(const List_Element_t * const Element_p) { /* Get the next element from the list */ return Element_p->Internal[1]; } /* end of file list.c */