/* ---------------------------------------------------- get the descriptor memory usage in bytes */ IX_STATUS ixAtmdAccDescMgmtMemoryUsageGet (unsigned int *descriptorMemoryUsagePtr) { IX_ATMDACC_ENSURE (initDone, "Initailisation Error"); IX_ATMDACC_DESCMGMT_LOCK(); /* sanity check */ IX_ATMDACC_ENSURE(npeDescCount <= IX_ATMDACC_MAX_NPE_DESCRIPTORS, "descriptor pool index corrupted"); /* sanity check */ IX_ATMDACC_ENSURE((descMgmtStats.allocateCount - descMgmtStats.releaseCount) == (IX_ATMDACC_MAX_NPE_DESCRIPTORS - npeDescCount) , "descriptor pool index corrupted"); /* get the memory usage */ *descriptorMemoryUsagePtr = (descMgmtStats.allocateCount - descMgmtStats.releaseCount) * sizeof (IxAtmdAccNpeDescriptor); IX_ATMDACC_DESCMGMT_UNLOCK(); return IX_SUCCESS; }
/* ---------------------------------------------------- release a NPE descriptor */ IX_STATUS ixAtmdAccDescNpeDescriptorRelease (IxAtmdAccNpeDescriptor* npeDescriptorPtr) { IX_STATUS returnStatus = IX_SUCCESS; IX_ATMDACC_ENSURE (initDone, "Initialisation Error"); IX_ATMDACC_ENSURE (npeDescriptorPtr != NULL, "Release null descriptor"); IX_ATMDACC_DESCMGMT_LOCK(); /* ensure pool availabilility */ IX_ATMDACC_ENSURE(npeDescCount < IX_ATMDACC_MAX_NPE_DESCRIPTORS, "running out of space in pool descriptor"); /* check pool availabilility */ if (npeDescCount < IX_ATMDACC_MAX_NPE_DESCRIPTORS) { /* put element to the pool */ npeDescriptorArray[npeDescCount++] = npeDescriptorPtr; /* update stats */ descMgmtStats.releaseCount++; } else { returnStatus = IX_FAIL; } /* end of if-else(npeDescCount) */ IX_ATMDACC_DESCMGMT_UNLOCK(); return returnStatus; }
/* ---------------------------------------------- */ PRIVATE IX_STATUS ixAtmdAccDummyStateChangeHandler (IxAtmLogicalPort port, IxAtmdAccPortState newState) { IX_ATMDACC_ENSURE(0, "PortMgmt No StateChange Handler Registered"); return IX_FAIL; }
/* ---------------------------------------------- */ PRIVATE IX_STATUS ixAtmdAccUtopiaStatusRead (IxAtmdAccUtopiaStatus *utStatus) { IX_STATUS returnStatus = IX_SUCCESS; UINT32 utStatusWords[sizeof(IxAtmdAccUtopiaStatus)/sizeof(UINT32)]; int numWords = sizeof(IxAtmdAccUtopiaStatus)/sizeof(UINT32); int wordCnt; UINT32 readOffset; IX_ATMDACC_ENSURE (numWords < 64, "out of bound structure"); ixOsalMemSet (utStatus, 0, sizeof (IxAtmdAccUtopiaStatus)); /* Read the status table from NPE memory */ for (wordCnt = 0; (wordCnt < numWords) && (returnStatus == IX_SUCCESS); wordCnt++) { /* offset to read */ readOffset = wordCnt * sizeof(UINT32); /* read the word of the status table at this offset */ returnStatus = ixAtmdAccUtilNpeMsgWithResponseSend( IX_NPE_A_MSSG_ATM_UTOPIA_STATUS_READ, readOffset, NPE_IGNORE, ixAtmdAccNpeStatusReadCallback); if (returnStatus == IX_SUCCESS) { /* Wait for ixAtmdAccNpeReadCallback to release */ IX_ATMDACC_NPE_RESPONSE_LOCK_GET (); /* Check the address matches the address from ixAtmdAccNpeReadCallback */ IX_ATMDACC_ENSURE (npeRespOffsetRead == readOffset, "Read error"); /* Copy the word read from NPE memory into the utopia status * structure. NOTE: npewordRead is set by ixAtmdAccNpeReadCallback */ utStatusWords[wordCnt] = npeRespWordRead; } /* end of if(returnStatus) */ } /* end of for(wordCnt) */ ixAtmdAccNpeStatusGenerate(utStatus,utStatusWords); return returnStatus; }
/* ---------------------------------------------- */ PRIVATE void ixAtmdAccNpeStatusReadCallback (IxNpeMhNpeId npeMhNpeId, IxNpeMhMessage npeMhMessage) { UINT32 id; /* Check NpeId */ IX_ATMDACC_ENSURE (npeMhNpeId == IX_NPEMH_NPEID_NPEA, "wrong npeMhNpeId"); /* Check Id */ id = npeMhMessage.data[0] & NPE_RESP_ID_MASK; IX_ATMDACC_ENSURE (id == NPE_UT_STATUS_READ_EXPECTED_ID, "wrong id"); npeRespOffsetRead = npeMhMessage.data[0] & NPE_RESP_OFFSET_MASK; npeRespWordRead = npeMhMessage.data[1]; /* Unblock the reading context */ IX_ATMDACC_NPE_RESPONSE_LOCK_RELEASE (); }
/* ---------------------------------------------------- get a NPE descriptor */ IX_STATUS ixAtmdAccDescNpeDescriptorGet (IxAtmdAccNpeDescriptor** npeDescriptorPtr) { IX_STATUS returnStatus = IX_SUCCESS; IX_ATMDACC_ENSURE (initDone, "Initialisation Error"); IX_ATMDACC_DESCMGMT_LOCK(); /* check parameter */ IX_ATMDACC_ENSURE (npeDescriptorPtr != NULL, "null pointer parameter"); /* sanity check */ IX_ATMDACC_ENSURE(npeDescCount <= IX_ATMDACC_MAX_NPE_DESCRIPTORS, "descriptor pool index corrupted"); /* check there is an entry in the pool */ IX_ATMDACC_ENSURE (npeDescCount > 0, "Pool size mismatch"); if (npeDescCount > 0) { /* get the descriptor from the pool */ *npeDescriptorPtr = npeDescriptorArray[--npeDescCount]; ixOsalMemSet(&(*npeDescriptorPtr)->npe, 0, sizeof((*npeDescriptorPtr)->npe)); /* update stats */ descMgmtStats.allocateCount++; } else { returnStatus = IX_FAIL; } /* end of if-else(npeDescCount) */ IX_ATMDACC_DESCMGMT_UNLOCK(); return returnStatus; }
/* ---------------------------------------------- */ PRIVATE void ixAtmdAccUtopiaConfigLoadCallback (IxNpeMhNpeId npeMhNpeId, IxNpeMhMessage npeMhMessage) { UINT32 id; UINT32 status; /* Check NpeId */ IX_ATMDACC_ENSURE (npeMhNpeId == IX_NPEMH_NPEID_NPEA, "wrong npeMhNpeId"); /* Check the ID */ id = npeMhMessage.data[0] & NPE_RESP_ID_MASK; IX_ATMDACC_ENSURE (id == NPE_UT_CONFIG_LOAD_EXPECTED_ID, "wrong id"); /* Check the status */ status = npeMhMessage.data[0] & NPE_RESP_STATUS_MASK; IX_ATMDACC_ENSURE (status == NPE_SUCCESS, "wrong status"); /* Unblock the config get context */ IX_ATMDACC_NPE_RESPONSE_LOCK_RELEASE (); }
/* ---------------------------------------------------- * Display current stats */ void ixAtmdAccDescMgmtStatsShow (void) { unsigned int currentDescCount; /* module descriptor allocated snapshot */ IxAtmdAccDescMgmtStats currentDescMgmtStats; /* module statistics snapshot */ unsigned int descSize = ((sizeof (IxAtmdAccNpeDescriptor) + (NPE_ADDR_ALIGN - 1)) / NPE_ADDR_ALIGN) * NPE_ADDR_ALIGN; /* get a snapshot */ IX_ATMDACC_DESCMGMT_LOCK(); currentDescMgmtStats = descMgmtStats; currentDescCount = npeDescCount; /* sanity check */ IX_ATMDACC_ENSURE((descMgmtStats.allocateCount - descMgmtStats.releaseCount) == (IX_ATMDACC_MAX_NPE_DESCRIPTORS - npeDescCount) , "descriptor pool index corrupted"); IX_ATMDACC_DESCMGMT_UNLOCK(); /* display the snapshot */ printf ("Npe Descriptors memory allocation\n"); printf ("Pool size in bytes ......... : %10u bytes\n", descSize * IX_ATMDACC_MAX_NPE_DESCRIPTORS); printf ("Descriptor size ............ : %10u bytes\n", (unsigned int)sizeof (IxAtmdAccNpeDescriptor)); printf ("Pool depth ................. : %10u descriptors\n", IX_ATMDACC_MAX_NPE_DESCRIPTORS); printf ("Alloc'd .................... : %10u\n", currentDescMgmtStats.allocateCount); printf ("Free'd ..................... : %10u\n", currentDescMgmtStats.releaseCount); printf ("Pool usage ................. : %10u descriptors\n", descMgmtStats.allocateCount - descMgmtStats.releaseCount); }
/* ---------------------------------------------- */ PRIVATE IX_STATUS ixAtmdAccUtopiaConfigWrite (const IxAtmdAccUtopiaConfig *utConfig) { IX_STATUS returnStatus = IX_SUCCESS; UINT32 npeWords[sizeof (IxAtmdAccUtopiaConfig) / sizeof (UINT32)]; int numWords = sizeof (IxAtmdAccUtopiaConfig) / sizeof (UINT32); int wordCnt; IX_ATMDACC_ENSURE (numWords < 64, "out of bound structure"); ixAtmdAccUtopiaConfigGenerate(utConfig, npeWords); /* Write one word of the config at a time to NPE-A */ for (wordCnt = 0; (wordCnt < numWords) && (returnStatus == IX_SUCCESS); wordCnt++) { returnStatus = ixAtmdAccUtilNpeMsgSend (IX_NPE_A_MSSG_ATM_UTOPIA_CONFIG_WRITE, wordCnt * sizeof(UINT32), npeWords[wordCnt]); } /* end of for(wordCnt) */ return returnStatus; }
/* --------------------------------------------------------- * Convert the requested number of cells to queue entries for NPE-A * * qMgrEntryPtr is a pointer to an internal array of entries * This array, when ready, will be flushed by the qMgr * physicalAddress : physical address of a NPE descriptor which is * bound to the PDU to be sent, or 0 for Idle cells * cellCount : number of cells to send (data cell or idle cell) * cellType : Type of the cells to send (data cells or idle cells) */ PRIVATE void ixAtmdAccCellTx (UINT32 **qMgrEntryPtr, unsigned int physicalAddress, unsigned int cellCount, unsigned int cellType) { IX_ATMDACC_ENSURE (cellCount != 0, "Bad cell count!"); /* The following algorthim is designed for performance and * is a variation on Duff's Device, which is widely documented. * - ``Duff's device'' had come up in comp.lang.c as soon as 1983 * - The device is to express general loop unrolling directly in C. * - The device is legal dpANS C. X3J11 considered it carefully and decided that it * was legal. The device is also legal C++, since Bjarne uses it in his book. * * The algorithm is designed to replace the following slow code * * while (cellCount > 15) * { qEntry = buildEntry(15 cells, physicaladdress, type); * qMgrWriteReturnStatus = qMgrWrite(...qEntry) * cellCount -= 15; * } * if (cellCount > 0) * { qEntry = buildEntry(cellCount, physicaladdress, type); * qMgrWriteReturnStatus = qMgrWrite(...qEntry) * } * return qMgrWriteReturnStatus * * The algorithm exploits * the fall through of the switch statement to process * successive queue entries of NPE_TX_MAXCELLS_PER_QENTRY cells, * Any residual cells are placed in the final queue entryin a separate step * after the loop ends. * This reduces the number of a control loop iterations by a factor of 8. */ if(cellCount > NPE_TX_MAXCELLS_PER_QENTRY) { /* get the number of qEntries with a full count of cells * using an integer division with round-down to the previous integer */ unsigned int qEntryCount = cellCount / NPE_TX_MAXCELLS_PER_QENTRY; /* get the number of iterations using an integer division * with round-up to the next integer */ unsigned int n = (qEntryCount + 7)/8; /* build one entry with the maximum of cells per entry . This queue * entry is always */ UINT32 qEntry = ixAtmdAccTxQueueEntryBuild (physicalAddress, NPE_TX_MAXCELLS_PER_QENTRY, cellType); /* store X queue entries with a number of cells * equal to NPE_TX_MAXCELLS_PER_QENTRY */ switch(qEntryCount & 7) { case 0: do { *(*qMgrEntryPtr)++ = qEntry; case 7: *(*qMgrEntryPtr)++ = qEntry; case 6: *(*qMgrEntryPtr)++ = qEntry; case 5: *(*qMgrEntryPtr)++ = qEntry; case 4: *(*qMgrEntryPtr)++ = qEntry; case 3: *(*qMgrEntryPtr)++ = qEntry; case 2: *(*qMgrEntryPtr)++ = qEntry; case 1: *(*qMgrEntryPtr)++ = qEntry; } while (--n > 0); } /* check for any more cells to process (sub and mul are faster than mod) * cellCount = qEntryCount % NPE_TX_MAXCELLS_PER_QENTRY */ cellCount -= qEntryCount * NPE_TX_MAXCELLS_PER_QENTRY; if(cellCount == 0) { /* all done (the number of cells was an * exact multiple of NPE_TX_MAXCELLS_PER_QENTRY */ return; } } /* store 1 queue entry with a number of cells * between 1 and NPE_TX_MAXCELLS_PER_QENTRY (included) */ *(*qMgrEntryPtr)++ = ixAtmdAccTxQueueEntryBuild (physicalAddress, cellCount, cellType); return; }
/* ---------------------------------------------- */ PRIVATE BOOL ixAtmdAccDummyStateQuery (IxAtmLogicalPort port) { IX_ATMDACC_ENSURE(0, "PortMgmt No State Check Registered"); return FALSE; }
/* ---------------------------------------------- */ PRIVATE void ixAtmdAccDummySetupNotifyHandler (unsigned int numPort) { IX_ATMDACC_ENSURE(0, "PortMgmt No Setup Handler Registered"); }