1/** 2 * @file IxNpeMhSolicitedCbMgr.c 3 * 4 * @author Intel Corporation 5 * @date 18 Jan 2002 6 * 7 * @brief This file contains the implementation of the private API for the 8 * Solicited Callback Manager module. 9 * 10 * 11 * @par 12 * IXP400 SW Release version 2.0 13 * 14 * -- Copyright Notice -- 15 * 16 * @par 17 * Copyright 2001-2005, Intel Corporation. 18 * All rights reserved. 19 * 20 * @par 21 * Redistribution and use in source and binary forms, with or without 22 * modification, are permitted provided that the following conditions 23 * are met: 24 * 1. Redistributions of source code must retain the above copyright 25 * notice, this list of conditions and the following disclaimer. 26 * 2. Redistributions in binary form must reproduce the above copyright 27 * notice, this list of conditions and the following disclaimer in the 28 * documentation and/or other materials provided with the distribution. 29 * 3. Neither the name of the Intel Corporation nor the names of its contributors 30 * may be used to endorse or promote products derived from this software 31 * without specific prior written permission. 32 * 33 * @par 34 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 35 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 38 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 40 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 41 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 42 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 43 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 44 * SUCH DAMAGE. 45 * 46 * @par 47 * -- End of Copyright Notice -- 48*/ 49#ifndef IXNPEMHCONFIG_P_H 50# define IXNPEMHSOLICITEDCBMGR_C 51#else 52# error "Error, IxNpeMhConfig_p.h should not be included before this definition." 53#endif 54 55/* 56 * Put the system defined include files required. 57 */ 58 59 60/* 61 * Put the user defined include files required. 62 */ 63 64#include "IxOsal.h" 65 66#include "IxNpeMhMacros_p.h" 67#include "IxNpeMhSolicitedCbMgr_p.h" 68#include "IxNpeMhConfig_p.h" 69/* 70 * #defines and macros used in this file. 71 */ 72 73/* 74 * Typedefs whose scope is limited to this file. 75 */ 76 77/** 78 * @struct IxNpeMhSolicitedCallbackListEntry 79 * 80 * @brief This structure is used to store the information associated with 81 * an entry in the callback list. This consists of the ID of the send 82 * message (which indicates the ID of the corresponding response message) 83 * and the callback function pointer itself. 84 * 85 */ 86 87typedef struct IxNpeMhSolicitedCallbackListEntry 88{ 89 /** message ID */ 90 IxNpeMhMessageId messageId; 91 92 /** callback function pointer */ 93 IxNpeMhCallback callback; 94 95 /** pointer to next entry in the list */ 96 struct IxNpeMhSolicitedCallbackListEntry *next; 97} IxNpeMhSolicitedCallbackListEntry; 98 99/** 100 * @struct IxNpeMhSolicitedCallbackList 101 * 102 * @brief This structure is used to maintain the list of response 103 * callbacks. The number of entries in this list will be variable, and 104 * they will be stored in a linked list fashion for ease of addition and 105 * removal. The entries themselves are statically allocated, and are 106 * organised into a "free" list and a "callback" list. Adding an entry 107 * means taking an entry from the "free" list and adding it to the 108 * "callback" list. Removing an entry means removing it from the 109 * "callback" list and returning it to the "free" list. 110 */ 111 112typedef struct 113{ 114 /** pointer to the head of the free list */ 115 IxNpeMhSolicitedCallbackListEntry *freeHead; 116 117 /** pointer to the head of the callback list */ 118 IxNpeMhSolicitedCallbackListEntry *callbackHead; 119 120 /** pointer to the tail of the callback list */ 121 IxNpeMhSolicitedCallbackListEntry *callbackTail; 122 123 /** array of entries - the first entry is used as a dummy entry to */ 124 /* avoid the scenario of having an empty list, hence '+ 1' */ 125 IxNpeMhSolicitedCallbackListEntry entries[IX_NPEMH_MAX_CALLBACKS + 1]; 126} IxNpeMhSolicitedCallbackList; 127 128/** 129 * @struct IxNpeMhSolicitedCbMgrStats 130 * 131 * @brief This structure is used to maintain statistics for the Solicited 132 * Callback Manager module. 133 */ 134 135typedef struct 136{ 137 UINT32 saves; /**< callback list saves */ 138 UINT32 retrieves; /**< callback list retrieves */ 139} IxNpeMhSolicitedCbMgrStats; 140 141/* 142 * Variable declarations global to this file only. Externs are followed by 143 * static variables. 144 */ 145 146PRIVATE IxNpeMhSolicitedCallbackList 147ixNpeMhSolicitedCbMgrCallbackLists[IX_NPEMH_NUM_NPES]; 148 149PRIVATE IxNpeMhSolicitedCbMgrStats 150ixNpeMhSolicitedCbMgrStats[IX_NPEMH_NUM_NPES]; 151 152/* 153 * Extern function prototypes. 154 */ 155 156/* 157 * Static function prototypes. 158 */ 159 160/* 161 * Function definition: ixNpeMhSolicitedCbMgrInitialize 162 */ 163 164void ixNpeMhSolicitedCbMgrInitialize (void) 165{ 166 IxNpeMhNpeId npeId; 167 UINT32 localIndex; 168 IxNpeMhSolicitedCallbackList *list = NULL; 169 170 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering " 171 "ixNpeMhSolicitedCbMgrInitialize\n"); 172 173 /* for each NPE ... */ 174 for (npeId = 0; npeId < IX_NPEMH_NUM_NPES; npeId++) 175 { 176 /* initialise a pointer to the list for convenience */ 177 list = &ixNpeMhSolicitedCbMgrCallbackLists[npeId]; 178 179 /* for each entry in the list, after the dummy entry ... */ 180 for (localIndex = 1; localIndex <= IX_NPEMH_MAX_CALLBACKS; localIndex++) 181 { 182 /* initialise the entry */ 183 list->entries[localIndex].messageId = 0x00; 184 list->entries[localIndex].callback = NULL; 185 186 /* if this entry is before the last entry */ 187 if (localIndex < IX_NPEMH_MAX_CALLBACKS) 188 { 189 /* chain this entry to the following entry */ 190 list->entries[localIndex].next = &(list->entries[localIndex + 1]); 191 } 192 else /* this entry is the last entry */ 193 { 194 /* the last entry isn't chained to anything */ 195 list->entries[localIndex].next = NULL; 196 } 197 } 198 199 /* set the free list pointer to point to the first real entry */ 200 /* (all real entries begin chained together on the free list) */ 201 list->freeHead = &(list->entries[1]); 202 203 /* set the callback list pointers to point to the dummy entry */ 204 /* (the callback list is initially empty) */ 205 list->callbackHead = &(list->entries[0]); 206 list->callbackTail = &(list->entries[0]); 207 } 208 209 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting " 210 "ixNpeMhSolicitedCbMgrInitialize\n"); 211} 212 213/* 214 * Function definition: ixNpeMhSolicitedCbMgrCallbackSave 215 */ 216 217IX_STATUS ixNpeMhSolicitedCbMgrCallbackSave ( 218 IxNpeMhNpeId npeId, 219 IxNpeMhMessageId solicitedMessageId, 220 IxNpeMhCallback solicitedCallback) 221{ 222 IxNpeMhSolicitedCallbackList *list = NULL; 223 IxNpeMhSolicitedCallbackListEntry *callbackEntry = NULL; 224 225 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Entering " 226 "ixNpeMhSolicitedCbMgrCallbackSave\n"); 227 228 /* initialise a pointer to the list for convenience */ 229 list = &ixNpeMhSolicitedCbMgrCallbackLists[npeId]; 230 231 /* check to see if there are any entries in the free list */ 232 if (list->freeHead == NULL) 233 { 234 IX_NPEMH_ERROR_REPORT ("Solicited callback list is full\n"); 235 return IX_FAIL; 236 } 237 238 /* there is an entry in the free list we can use */ 239 240 /* update statistical info */ 241 ixNpeMhSolicitedCbMgrStats[npeId].saves++; 242 243 /* remove a callback entry from the start of the free list */ 244 callbackEntry = list->freeHead; 245 list->freeHead = callbackEntry->next; 246 247 /* fill in the callback entry with the new data */ 248 callbackEntry->messageId = solicitedMessageId; 249 callbackEntry->callback = solicitedCallback; 250 251 /* the new callback entry will be added to the tail of the callback */ 252 /* list, so it isn't chained to anything */ 253 callbackEntry->next = NULL; 254 255 /* chain new callback entry to the last entry of the callback list */ 256 list->callbackTail->next = callbackEntry; 257 list->callbackTail = callbackEntry; 258 259 IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting " 260 "ixNpeMhSolicitedCbMgrCallbackSave\n"); 261 262 return IX_SUCCESS; 263} 264 265/* 266 * Function definition: ixNpeMhSolicitedCbMgrCallbackRetrieve 267 */ 268 269void ixNpeMhSolicitedCbMgrCallbackRetrieve ( 270 IxNpeMhNpeId npeId, 271 IxNpeMhMessageId solicitedMessageId, 272 IxNpeMhCallback *solicitedCallback) 273{ 274 IxNpeMhSolicitedCallbackList *list = NULL; 275 IxNpeMhSolicitedCallbackListEntry *callbackEntry = NULL; 276 IxNpeMhSolicitedCallbackListEntry *previousEntry = NULL; 277 278 /* initialise a pointer to the list for convenience */ 279 list = &ixNpeMhSolicitedCbMgrCallbackLists[npeId]; 280 281 /* initialise the callback entry to the first entry of the callback */ 282 /* list - we must skip over the dummy entry, which is the previous */ 283 callbackEntry = list->callbackHead->next; 284 previousEntry = list->callbackHead; 285 286 /* traverse the callback list looking for an entry with a matching */ 287 /* message ID. note we also save the previous entry's pointer to */ 288 /* allow us to unchain the matching entry from the callback list */ 289 while ((callbackEntry != NULL) && 290 (callbackEntry->messageId != solicitedMessageId)) 291 { 292 previousEntry = callbackEntry; 293 callbackEntry = callbackEntry->next; 294 } 295 296 /* if we didn't find a matching callback entry */ 297 if (callbackEntry == NULL) 298 { 299 /* return a NULL callback in the outgoing parameter */ 300 *solicitedCallback = NULL; 301 } 302 else /* we found a matching callback entry */ 303 { 304 /* update statistical info */ 305 ixNpeMhSolicitedCbMgrStats[npeId].retrieves++; 306 307 /* return the callback in the outgoing parameter */ 308 *solicitedCallback = callbackEntry->callback; 309 310 /* unchain callback entry by chaining previous entry to next */ 311 previousEntry->next = callbackEntry->next; 312 313 /* if the callback entry is at the tail of the list */ 314 if (list->callbackTail == callbackEntry) 315 { 316 /* update the tail of the callback list */ 317 list->callbackTail = previousEntry; 318 } 319 320 /* re-initialise the callback entry */ 321 callbackEntry->messageId = 0x00; 322 callbackEntry->callback = NULL; 323 324 /* add the callback entry to the start of the free list */ 325 callbackEntry->next = list->freeHead; 326 list->freeHead = callbackEntry; 327 } 328} 329 330/* 331 * Function definition: ixNpeMhSolicitedCbMgrShow 332 */ 333 334void ixNpeMhSolicitedCbMgrShow ( 335 IxNpeMhNpeId npeId) 336{ 337 /* show the solicited callback list save counter */ 338 IX_NPEMH_SHOW ("Solicited callback list saves", 339 ixNpeMhSolicitedCbMgrStats[npeId].saves); 340 341 /* show the solicited callback list retrieve counter */ 342 IX_NPEMH_SHOW ("Solicited callback list retrieves", 343 ixNpeMhSolicitedCbMgrStats[npeId].retrieves); 344} 345 346/* 347 * Function definition: ixNpeMhSolicitedCbMgrShowReset 348 */ 349 350void ixNpeMhSolicitedCbMgrShowReset ( 351 IxNpeMhNpeId npeId) 352{ 353 /* reset the solicited callback list save counter */ 354 ixNpeMhSolicitedCbMgrStats[npeId].saves = 0; 355 356 /* reset the solicited callback list retrieve counter */ 357 ixNpeMhSolicitedCbMgrStats[npeId].retrieves = 0; 358} 359