/** * @file IxPiuMhSolicitedCbMgr.c * * @author Intel Corporation * @date 18 Jan 2002 * * @description Contents are the implementation of the private API for * the Solicited Callback Manager module. * * * @par * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form 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. * * 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 * OWNER 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 IXPIUMHCONFIG_P_H # define IXPIUMHSOLICITEDCBMGR_C #else # error "Error, IxPiuMhConfig_p.h should not be included before this defn." #endif /* * Put the system defined include files required. */ /* * Put the user defined include files required. */ #include "IxOsal.h" #include "IxPiuMhMacros_p.h" #include "IxPiuMhSolicitedCbMgr_p.h" #include "IxPiuMhConfig_p.h" /* * #defines and macros used in this file. */ /* * Typedefs whose scope is limited to this file. */ /** * @struct IxPiuMhSolicitedCallbackListEntry * * @brief This structure is used to store the information associated with * an entry in the callback list. This consists of the ID of the send * message (which indicates the ID of the corresponding response message) * and the callback function pointer itself. * */ typedef struct IxPiuMhSolicitedCallbackListEntry { /** message ID */ IxPiuMhMessageId messageId; /** callback function pointer */ IxPiuMhCallback callback; /** pointer to next entry in the list */ struct IxPiuMhSolicitedCallbackListEntry *next; } IxPiuMhSolicitedCallbackListEntry; /** * @struct IxPiuMhSolicitedCallbackList * * @brief This structure is used to maintain the list of response * callbacks. The number of entries in this list will be variable, and * they will be stored in a linked list fashion for ease of addition and * removal. The entries themselves are statically allocated, and are * organised into a "free" list and a "callback" list. Adding an entry * means taking an entry from the "free" list and adding it to the * "callback" list. Removing an entry means removing it from the * "callback" list and returning it to the "free" list. */ typedef struct { /** pointer to the head of the free list */ IxPiuMhSolicitedCallbackListEntry *freeHead; /** pointer to the head of the callback list */ IxPiuMhSolicitedCallbackListEntry *callbackHead; /** pointer to the tail of the callback list */ IxPiuMhSolicitedCallbackListEntry *callbackTail; /** array of entries - the first entry is used as a dummy entry to */ /* avoid the scenario of having an empty list, hence '+ 1' */ IxPiuMhSolicitedCallbackListEntry entries[IX_PIUMH_MAX_CALLBACKS + 1]; } IxPiuMhSolicitedCallbackList; /** * @struct IxPiuMhSolicitedCbMgrStats * * @brief This structure is used to maintain statistics for the Solicited * Callback Manager module. */ typedef struct { UINT32 saves; /**< callback list saves */ UINT32 retrieves; /**< callback list retrieves */ } IxPiuMhSolicitedCbMgrStats; /* * Variable declarations global to this file only. Externs are followed by * static variables. */ PRIVATE IxPiuMhSolicitedCallbackList ixPiuMhSolicitedCbMgrCallbackLists[IX_PIUMH_NUM_PIUS]; PRIVATE IxPiuMhSolicitedCbMgrStats ixPiuMhSolicitedCbMgrStats[IX_PIUMH_NUM_PIUS]; /* * Extern function prototypes. */ /* * Static function prototypes. */ /* * Function definition: ixPiuMhSolicitedCbMgrInitialize */ void ixPiuMhSolicitedCbMgrInitialize (void) { IxPiuMhPiuId piuId; UINT32 localIndex; IxPiuMhSolicitedCallbackList *list = NULL; IX_PIUMH_TRACE0 (IX_PIUMH_FN_ENTRY_EXIT, "Entering " "ixPiuMhSolicitedCbMgrInitialize\n"); /* for each PIU ... */ for (piuId = 0; piuId < IX_PIUMH_NUM_PIUS; piuId++) { /* initialise a pointer to the list for convenience */ list = &ixPiuMhSolicitedCbMgrCallbackLists[piuId]; /* for each entry in the list, after the dummy entry ... */ for (localIndex = 1; localIndex <= IX_PIUMH_MAX_CALLBACKS; localIndex++) { /* initialise the entry */ list->entries[localIndex].messageId = 0x00; list->entries[localIndex].callback = NULL; /* if this entry is before the last entry */ if (localIndex < IX_PIUMH_MAX_CALLBACKS) { /* chain this entry to the following entry */ list->entries[localIndex].next = &(list->entries[localIndex + 1]); } else /* this entry is the last entry */ { /* the last entry isn't chained to anything */ list->entries[localIndex].next = NULL; } } /* set the free list pointer to point to the first real entry */ /* (all real entries begin chained together on the free list) */ list->freeHead = &(list->entries[1]); /* set the callback list pointers to point to the dummy entry */ /* (the callback list is initially empty) */ list->callbackHead = &(list->entries[0]); list->callbackTail = &(list->entries[0]); } IX_PIUMH_TRACE0 (IX_PIUMH_FN_ENTRY_EXIT, "Exiting " "ixPiuMhSolicitedCbMgrInitialize\n"); } /* * Function definition: ixPiuMhSolicitedCbMgrUninitialize */ void ixPiuMhSolicitedCbMgrUninitialize (void) { IxPiuMhPiuId piuId; UINT32 localIndex; IxPiuMhSolicitedCallbackList *list; IX_PIUMH_TRACE0 (IX_PIUMH_FN_ENTRY_EXIT, "Entering " "ixPiuMhSolicitedCbMgrUninitialize\n"); /* for each PIU ... */ for (piuId = 0; piuId < IX_PIUMH_NUM_PIUS; piuId++) { /* initialise a pointer to the list for convenience */ list = &ixPiuMhSolicitedCbMgrCallbackLists[piuId]; /* for each entry in the list, after the dummy entry ... */ for (localIndex = 1; localIndex <= IX_PIUMH_MAX_CALLBACKS; localIndex++) { /* initialise the entry */ list->entries[localIndex].messageId = 0x00; list->entries[localIndex].callback = NULL; /* if this entry is before the last entry */ if (IX_PIUMH_MAX_CALLBACKS > localIndex) { /* chain this entry to the following entry */ list->entries[localIndex].next = &(list->entries[localIndex + 1]); } else /* this entry is the last entry */ { /* the last entry isn't chained to anything */ list->entries[localIndex].next = NULL; } } /* set the free list pointer to point to the first real entry */ /* (all real entries begin chained together on the free list) */ list->freeHead = &(list->entries[1]); /* set the callback list pointers to point to the dummy entry */ /* (the callback list is initially empty) */ list->callbackHead = &(list->entries[0]); list->callbackTail = &(list->entries[0]); } IX_PIUMH_TRACE0 (IX_PIUMH_FN_ENTRY_EXIT, "Exiting " "ixPiuMhSolicitedCbMgrUninitialize\n"); } /* * Function definition: ixPiuMhSolicitedCbMgrCallbackSave */ IX_STATUS ixPiuMhSolicitedCbMgrCallbackSave ( IxPiuMhPiuId piuId, IxPiuMhMessageId solicitedMessageId, IxPiuMhCallback solicitedCallback) { IxPiuMhSolicitedCallbackList *list = NULL; IxPiuMhSolicitedCallbackListEntry *callbackEntry = NULL; IX_PIUMH_TRACE0 (IX_PIUMH_FN_ENTRY_EXIT, "Entering " "ixPiuMhSolicitedCbMgrCallbackSave\n"); /* initialise a pointer to the list for convenience */ list = &ixPiuMhSolicitedCbMgrCallbackLists[piuId]; /* check to see if there are any entries in the free list */ if (list->freeHead == NULL) { IX_PIUMH_ERROR_REPORT ("Solicited callback list is full\n"); return IX_FAIL; } /* there is an entry in the free list we can use */ /* update statistical info */ ixPiuMhSolicitedCbMgrStats[piuId].saves++; /* remove a callback entry from the start of the free list */ callbackEntry = list->freeHead; list->freeHead = callbackEntry->next; /* fill in the callback entry with the new data */ callbackEntry->messageId = solicitedMessageId; callbackEntry->callback = solicitedCallback; /* the new callback entry will be added to the tail of the callback */ /* list, so it isn't chained to anything */ callbackEntry->next = NULL; /* chain new callback entry to the last entry of the callback list */ list->callbackTail->next = callbackEntry; list->callbackTail = callbackEntry; IX_PIUMH_TRACE0 (IX_PIUMH_FN_ENTRY_EXIT, "Exiting " "ixPiuMhSolicitedCbMgrCallbackSave\n"); return IX_SUCCESS; } /* * Function definition: ixPiuMhSolicitedCbMgrCallbackRetrieve */ void ixPiuMhSolicitedCbMgrCallbackRetrieve ( IxPiuMhPiuId piuId, IxPiuMhMessageId solicitedMessageId, IxPiuMhCallback *solicitedCallback) { IxPiuMhSolicitedCallbackList *list = NULL; IxPiuMhSolicitedCallbackListEntry *callbackEntry = NULL; IxPiuMhSolicitedCallbackListEntry *previousEntry = NULL; /* initialise a pointer to the list for convenience */ list = &ixPiuMhSolicitedCbMgrCallbackLists[piuId]; /* initialise the callback entry to the first entry of the callback */ /* list - we must skip over the dummy entry, which is the previous */ if (list != NULL) { callbackEntry = list->callbackHead->next; previousEntry = list->callbackHead; } /* traverse the callback list looking for an entry with a matching */ /* message ID. note we also save the previous entry's pointer to */ /* allow us to unchain the matching entry from the callback list */ while ((callbackEntry != NULL) && (callbackEntry->messageId != solicitedMessageId)) { previousEntry = callbackEntry; callbackEntry = callbackEntry->next; } /* if we didn't find a matching callback entry */ if (callbackEntry == NULL) { /* return a NULL callback in the outgoing parameter */ *solicitedCallback = NULL; } else /* we found a matching callback entry */ { /* update statistical info */ ixPiuMhSolicitedCbMgrStats[piuId].retrieves++; /* return the callback in the outgoing parameter */ *solicitedCallback = callbackEntry->callback; /* unchain callback entry by chaining previous entry to next */ previousEntry->next = callbackEntry->next; /* if the callback entry is at the tail of the list */ if (list->callbackTail == callbackEntry) { /* update the tail of the callback list */ list->callbackTail = previousEntry; } /* re-initialise the callback entry */ callbackEntry->messageId = 0x00; callbackEntry->callback = NULL; /* add the callback entry to the start of the free list */ callbackEntry->next = list->freeHead; list->freeHead = callbackEntry; } } /* * Function definition: ixPiuMhSolicitedCbMgrShow */ void ixPiuMhSolicitedCbMgrShow ( IxPiuMhPiuId piuId) { /* show the solicited callback list save counter */ IX_PIUMH_SHOW ("Solicited callback list saves", ixPiuMhSolicitedCbMgrStats[piuId].saves); /* show the solicited callback list retrieve counter */ IX_PIUMH_SHOW ("Solicited callback list retrieves", ixPiuMhSolicitedCbMgrStats[piuId].retrieves); } /* * Function definition: ixPiuMhSolicitedCbMgrShowReset */ void ixPiuMhSolicitedCbMgrShowReset ( IxPiuMhPiuId piuId) { /* reset the solicited callback list save counter */ ixPiuMhSolicitedCbMgrStats[piuId].saves = 0; /* reset the solicited callback list retrieve counter */ ixPiuMhSolicitedCbMgrStats[piuId].retrieves = 0; }