📄 sb.c
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// SB.C
//
// Socket Buffer
//
// Author: Michael A. Denio
// Copyright 1999 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
//--------------------------------------------------------------------
// SBNew()
//
// Creates a Socket Buffer
//--------------------------------------------------------------------
HANDLE SBNew( INT32 Max, INT32 Min, uint Mode )
{
SB *pSB;
#ifdef _STRONG_CHECKING
// Verify legal mode
if( Mode!=SB_MODE_LINEAR && Mode!=SB_MODE_ATOMIC && Mode!=SB_MODE_HYBRID )
{
DbgPrintf(DBG_WARN,"SBNew: Illegal Mode");
return(0);
}
#endif
// Allocate Object
if( !(pSB = mmAlloc(sizeof(SB))) )
{
DbgPrintf(DBG_WARN,"SBNew: Object OOM");
ExecLowResource();
return(0);
}
// Zero-init Object
mmZeroInit( pSB, sizeof(SB) );
// Allocate external buffer if LINEAR
if( Mode == SB_MODE_LINEAR && Max )
{
pSB->pData = mmBulkAlloc( Max );
if( !pSB->pData )
{
DbgPrintf(DBG_WARN,"SBNew: Buffer OOM");
mmFree( pSB );
return(0);
}
}
// Initialize type
pSB->Type = HTYPE_SB;
pSB->Mode = Mode;
// Initialize the object
pSB->Max = Max;
pSB->Min = Min;
return( (HANDLE)pSB );
}
//--------------------------------------------------------------------
// SBFree()
//
// Frees a SB
//--------------------------------------------------------------------
void SBFree( HANDLE h )
{
SB *pSB = (SB *)h;
#ifdef _STRONG_CHECKING
if( pSB->Type != HTYPE_SB )
{
DbgPrintf(DBG_ERROR,"SBFree: HTYPE %04x",pSB->Type);
return;
}
#endif
// Kill type for debug
pSB->Type = 0;
if( pSB->Mode == SB_MODE_LINEAR )
{
// Free the data buffer
if( pSB->pData )
mmBulkFree( pSB->pData );
}
else
{
// Free the Frags
if( pSB->hFragFirst )
FragFree( pSB->hFragFirst );
}
// Free the SB
mmFree( pSB );
}
//--------------------------------------------------------------------
// SBFlush()
//
// Flush all data in SB and free associated buffer when fFree set
//--------------------------------------------------------------------
void SBFlush( HANDLE h, uint fFree )
{
SB *pSB = (SB *)h;
#ifdef _STRONG_CHECKING
if( pSB->Type != HTYPE_SB )
{
DbgPrintf(DBG_ERROR,"SBFlush: HTYPE %04x",pSB->Type);
return;
}
#endif
// Zap the total
pSB->Total = 0;
if( pSB->Mode == SB_MODE_LINEAR )
{
// Reset the object
pSB->Head = pSB->Tail = 0;
if( fFree && pSB->pData )
{
// Free Data Buffer
mmBulkFree( pSB->pData );
pSB->pData = 0;
}
}
else
{
// Free all Frags
if( pSB->hFragFirst )
FragFree( pSB->hFragFirst );
pSB->hFragFirst = 0;
}
}
//--------------------------------------------------------------------
// SBRead()
//
// Read data from a SB
//--------------------------------------------------------------------
INT32 SBRead
(
HANDLE h,
INT32 Size,
INT32 Off,
UINT8 *pbDst,
IPN *pIPFrom,
uint *pPortFrom,
UINT8 flagPeek
)
{
SB *pSB = (SB *)h;
#ifdef _STRONG_CHECKING
if( pSB->Type != HTYPE_SB )
{
DbgPrintf(DBG_ERROR,"SBRead: HTYPE %04x",pSB->Type);
return( 0 );
}
#endif
if( pSB->Mode == SB_MODE_LINEAR )
{
//
// Linear Case
//
INT32 Len;
// Adjust size if too large
if( (Size+Off) > pSB->Total )
Size = pSB->Total - Off;
if( Size <= 0 )
return( Size );
// Copy data when pointer supplied
if( pbDst )
{
// First Copy
Len = pSB->Max - (pSB->Tail+Off);
if( Len >= 0 )
{
if( Len > Size )
Len = Size;
if( Len )
mmCopy( pbDst, pSB->pData + pSB->Tail + Off, (uint)Len );
// Copy the potential second block
if( Size > Len )
{
// Len is the number of bytes already copied
mmCopy( pbDst+Len, pSB->pData, (uint)(Size-Len) );
}
}
else
{
// Here Len is the additional offset from the start
Len = 0-Len;
mmCopy( pbDst, pSB->pData+Len, (uint)Size );
}
}
// Advance the tail pointer and adjust Total if not "peeking"
if( !flagPeek )
{
pSB->Tail = (pSB->Tail+(Size+Off))%pSB->Max;
pSB->Total -= (Size+Off);
}
return( Size );
}
else
{
//
// Atomic Case
//
uint ValidLen, Offset;
HANDLE hFrag;
INT32 BytesCopied,ToCopy;
UINT8 *pData;
// Get the first frag
hFrag = pSB->hFragFirst;
// There must be a first frag
if( !hFrag )
{
DbgPrintf(DBG_ERROR,"SBRead: Internal ATOMIC error");
return(0);
}
// Copy in the "from" stuff
if( pIPFrom )
*pIPFrom = FragGetAux2( hFrag );
if( pPortFrom )
*pPortFrom = (uint)FragGetAux1( hFrag );
BytesCopied = 0;
for(;;)
{
// Get the buffer info
pData = FragGetBufParams( hFrag, 0, &ValidLen, &Offset );
// Get the most bytes we can copy this frag
ToCopy = (INT32)ValidLen;
// If we don't want the entire frag, trim it down
if( (BytesCopied + ToCopy) > Size )
ToCopy = Size - BytesCopied;
// Copy the data from the frag
if( ToCopy )
mmCopy( pbDst + BytesCopied, pData + Offset, (uint)ToCopy );
BytesCopied += ToCopy;
// Handle ATOMIC mode
if( pSB->Mode == SB_MODE_ATOMIC )
{
// If not "peeking", then fix the frag list and the totals
if( !flagPeek )
{
pSB->Total -= (INT32)ValidLen;
pSB->hFragFirst = FragGetNext( hFrag );
FragSetNext( hFrag, 0 );
FragFree( hFrag );
}
break;
}
//
// Here we are in HYBRID mode
//
// If "peeking", just get next frag
if( flagPeek )
hFrag = FragGetNext( hFrag );
else
{
// Fix the frag list and the totals
pSB->Total -= ToCopy;
if( ToCopy == (INT32)ValidLen )
{
// We used the whole frag, remove it
pSB->hFragFirst = FragGetNext( hFrag );
FragSetNext( hFrag, 0 );
FragFree( hFrag );
hFrag = pSB->hFragFirst;
}
else
{
// Some data left - patch frag
Offset += (uint)ToCopy;
ValidLen -= (uint)ToCopy;
FragSetBufParams( hFrag, ValidLen, Offset );
break;
}
}
// Stop if we've copied the full request or out of frags
if( BytesCopied == Size || !hFrag )
break;
}
return( BytesCopied );
}
}
//--------------------------------------------------------------------
// SBReadNC()
//
// Read data without copy from a SB
//--------------------------------------------------------------------
HANDLE SBReadNC( HANDLE h, IPN *pIPFrom, uint *pPortFrom )
{
SB *pSB = (SB *)h;
#ifdef _STRONG_CHECKING
if( pSB->Type != HTYPE_SB )
{
DbgPrintf(DBG_ERROR,"SBReadNC: HTYPE %04x",pSB->Type);
return( 0 );
}
#endif
if( pSB->Mode == SB_MODE_LINEAR )
return(0);
else
{
//
// Atomic Case
//
uint ValidLen, Offset;
HANDLE hFrag;
// Get the first frag
hFrag = pSB->hFragFirst;
// There must be a first frag
if( !hFrag )
{
DbgPrintf(DBG_ERROR,"SBReadNC: Internal ATOMIC error");
return(0);
}
// Copy in the "from" stuff
if( pIPFrom )
*pIPFrom = FragGetAux2( hFrag );
if( pPortFrom )
*pPortFrom = (uint)FragGetAux1( hFrag );
// Get the buffer info
FragGetBufParams( hFrag, 0, &ValidLen, &Offset );
// Remove the frag
pSB->Total -= (INT32)ValidLen;
pSB->hFragFirst = FragGetNext( hFrag );
FragSetNext( hFrag, 0 );
return( hFrag );
}
}
//--------------------------------------------------------------------
// SBWrite()
//
// Write data (or attach frags) to a SB
//--------------------------------------------------------------------
INT32 SBWrite( HANDLE h, INT32 Size, void *pData, HANDLE hFrag )
{
SB *pSB = (SB *)h;
#ifdef _STRONG_CHECKING
if( pSB->Type != HTYPE_SB )
{
DbgPrintf(DBG_ERROR,"SBWrite: HTYPE %04x",pSB->Type);
return( 0 );
}
#endif
if( pSB->Mode == SB_MODE_LINEAR )
{
//
// Linear Case
//
INT32 Len;
// Adjust size if too large
Len = pSB->Max - pSB->Total;
if( Size > Len )
Size = Len;
// Copy data
if( !pSB->pData )
Size = 0;
else if( Size )
{
// First Copy
Len = pSB->Max - pSB->Head;
if( Len > Size )
Len = Size;
if( Len )
mmCopy( pSB->pData + pSB->Head, (UINT8 *)pData, (uint)Len );
// Potential Second Copy
if( Size > Len )
mmCopy( pSB->pData, ((UINT8 *)pData)+Len, (uint)(Size-Len) );
// Advance head pointer and ajdust Total
pSB->Head = (pSB->Head+Size)%pSB->Max;
pSB->Total += Size;
}
// Free frag if provided
if( hFrag )
FragFree( hFrag );
}
else
{
//
// Atomic Case
//
if( !hFrag )
{
DbgPrintf(DBG_ERROR,"SBWrite: No Frag");
return( 0 );
}
// Normally the caller is charged with preparing the frag
// for appending, but if a pointer is supplied, then
// we do it here
if( pData )
{
UINT8 *pDataOrg;
uint Offset;
pDataOrg = FragGetBufParams( hFrag, 0, 0, 0 );
Offset = (uint)(((UINT8 *)pData - pDataOrg));
FragSetBufParams( hFrag, (uint)Size, Offset );
}
// Put this frag (chain) in the list
if( !pSB->hFragFirst )
pSB->hFragFirst = hFrag;
else
FragSetNext( pSB->hFragLast, hFrag );
// Get the the new "last" frag
do { pSB->hFragLast = hFrag; }
while( hFrag = FragGetNext( pSB->hFragLast ) );
// Adjust our count
pSB->Total += Size;
}
return( Size );
}
//
// The following functions are direct structure references when
// _STRONG_CHECKING is not defined
//
#ifdef _STRONG_CHECKING
//--------------------------------------------------------------------
// SBGetTotal()
//
// Get the total bytes held in a SB
//--------------------------------------------------------------------
INT32 SBGetTotal( HANDLE h )
{
SB *pSB = (SB *)h;
if( pSB->Type != HTYPE_SB )
{
DbgPrintf(DBG_ERROR,"SBGetTotal: HTYPE %04x",pSB->Type);
return(0);
}
// Return Total
return( pSB->Total );
}
//--------------------------------------------------------------------
// SBGetMax()
//
// Get the max bytes held in a SB
//--------------------------------------------------------------------
INT32 SBGetMax( HANDLE h )
{
SB *pSB = (SB *)h;
if( pSB->Type != HTYPE_SB )
{
DbgPrintf(DBG_ERROR,"SBGetMax: HTYPE %04x",pSB->Type);
return(0);
}
// Return Max
return( pSB->Max );
}
//--------------------------------------------------------------------
// SBGetMin()
//
// Get the min byte threshold of a SB
//--------------------------------------------------------------------
INT32 SBGetMin( HANDLE h )
{
SB *pSB = (SB *)h;
if( pSB->Type != HTYPE_SB )
{
DbgPrintf(DBG_ERROR,"SBGetMin: HTYPE %04x",pSB->Type);
return(0);
}
// Return Min
return( pSB->Min );
}
//--------------------------------------------------------------------
// SBSetMin()
//
// Set the min byte threshold of a SB
//--------------------------------------------------------------------
void SBSetMin( HANDLE h, UINT32 value )
{
SB *pSB = (SB *)h;
if( pSB->Type != HTYPE_SB )
{
DbgPrintf(DBG_ERROR,"SBSetMin: HTYPE %04x",pSB->Type);
return;
}
// Set Min
pSB->Min = value;
}
//--------------------------------------------------------------------
// SBGetSpace()
//
// Get the space available in a SB
//--------------------------------------------------------------------
INT32 SBGetSpace( HANDLE h )
{
SB *pSB = (SB *)h;
if( pSB->Type != HTYPE_SB )
{
DbgPrintf(DBG_ERROR,"SBGetSpace: HTYPE %04x",pSB->Type);
return(0);
}
// Return free space
return( pSB->Max - pSB->Total );
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -