|
|
// Copyright (c) 1997, Microsoft Corporation, all rights reserved
// Copyright (c) 1997, Parallel Technologies, Inc., all rights reserved
//
// util.c
// DirectParallel WAN mini-port/call-manager driver
// General utility routines
//
// 01/07/97 Steve Cobb
// 09/15/97 Jay Lowe, Parallel Technologies, Inc.
#include "ptiwan.h"
//-----------------------------------------------------------------------------
// Local prototypes (alphabetically)
//-----------------------------------------------------------------------------
ULONG atoul( IN CHAR* pszNumber );
VOID ReversePsz( IN OUT CHAR* psz );
VOID ultoa( IN ULONG ul, OUT CHAR* pszBuf );
//-----------------------------------------------------------------------------
// General utility routines (alphabetically)
//-----------------------------------------------------------------------------
VOID ClearFlags( IN OUT ULONG* pulFlags, IN ULONG ulMask )
// Set 'ulMask' bits in '*pulFlags' flags as an interlocked operation.
//
{ ULONG ulFlags; ULONG ulNewFlags;
do { ulFlags = ReadFlags( pulFlags ); ulNewFlags = ulFlags & ~(ulMask); } while (InterlockedCompareExchange( pulFlags, ulNewFlags, ulFlags ) != (LONG)ulFlags); }
VOID IndicateLinkStatus( IN VCCB* pVc )
// Indicate new WAN_CO_LINKPARAMS settings for 'pVc' to NDISWAN.
//
{ ADAPTERCB* pAdapter; WAN_CO_LINKPARAMS params;
pAdapter = pVc->pAdapter;
params.TransmitSpeed = pVc->ulConnectBps; params.ReceiveSpeed = params.TransmitSpeed; params.SendWindow = 1; TRACE( TL_N, TM_Mp, ( "NdisMCoIndStatus(LINK) cid=%d bps=%d sw=%d", pVc->usCallId, params.TransmitSpeed, params.SendWindow ) ); NdisMCoIndicateStatus( pAdapter->MiniportAdapterHandle, pVc->NdisVcHandle, NDIS_STATUS_WAN_CO_LINKPARAMS, ¶ms, sizeof(params) ); TRACE( TL_N, TM_Mp, ( "NdisMCoIndStatus done" ) ); }
ULONG ReadFlags( IN ULONG* pulFlags )
// Read the value of '*pulFlags' as an interlocked operation.
//
{ return InterlockedExchangeAdd( pulFlags, 0 ); }
NDIS_STATUS ScheduleWork( IN ADAPTERCB* pAdapter, IN NDIS_PROC pProc, IN PVOID pContext )
// Schedules a PASSIVE IRQL callback to routine 'pProc' which will be
// passed 'pContext'. 'PAdapter' is the adapter control block from which
// the work item is allocated. This routine takes an adapter reference
// that should be removed by the called 'pProc'.
//
// Returns NDIS_STATUS_SUCCESS or an error code.
//
{ NDIS_STATUS status; NDIS_WORK_ITEM* pWork;
pWork = ALLOC_NDIS_WORK_ITEM( pAdapter ); if (!pWork) { ASSERT( !"Alloc work?" ); return NDIS_STATUS_RESOURCES; }
NdisInitializeWorkItem( pWork, pProc, pContext );
ReferenceAdapter( pAdapter ); status = NdisScheduleWorkItem( pWork ); if (status != NDIS_STATUS_SUCCESS) { ASSERT( !"SchedWork?" ); FREE_NDIS_WORK_ITEM( pAdapter, pWork ); DereferenceAdapter( pAdapter ); }
return status; }
VOID SetFlags( IN OUT ULONG* pulFlags, IN ULONG ulMask )
// Set 'ulMask' bits in '*pulFlags' flags as an interlocked operation.
//
{ ULONG ulFlags; ULONG ulNewFlags;
do { ulFlags = ReadFlags( pulFlags ); ulNewFlags = ulFlags | ulMask; } while (InterlockedCompareExchange( pulFlags, ulNewFlags, ulFlags ) != (LONG )ulFlags); }
ULONG StrCmp( IN LPSTR cs, IN LPSTR ct, ULONG n ) // Return 0 if string cs = string ct for length n
//
{ char ret=0;
while (n--) { ret = *cs - *ct;
if (ret) break;
cs++; ct++; }
return (ULONG)ret; }
ULONG StrCmpW( IN WCHAR* psz1, IN WCHAR* psz2 )
// Returns 0 if 'psz1' matches 'psz2'.
//
{ WCHAR pch;
pch = (WCHAR )0; while (*psz1 && *psz2) { pch = *psz1 - *psz2; if (pch) { break; }
psz1++; psz2++; }
return (ULONG )pch; }
VOID StrCpyW( IN WCHAR* psz1, IN WCHAR* psz2 )
// Copies 'psz2' to 'psz1'.
//
{ while (*psz2) { *psz1++ = *psz2++; }
*psz1 = L'\0'; }
CHAR* StrDup( IN CHAR* psz )
// Return a duplicate of 'psz'. Caller must eventually call FREE_NONPAGED
// on the returned string.
//
{ return StrDupSized( psz, strlen( psz ), 0 ); }
CHAR* StrDupNdisString( IN NDIS_STRING* pNdisString )
// Returns null-terminated ASCII copy of the NDIS_STRING 'pNdisString'
// Caller must eventually call FREE_NONPAGED on the returned string.
//
{ CHAR* pszDup;
pszDup = ALLOC_NONPAGED( pNdisString->Length + 1, MTAG_UTIL ); if (pszDup) { NdisZeroMemory( pszDup, pNdisString->Length + 1 ); if (pNdisString->Length) { NdisMoveMemory( pszDup, pNdisString->Buffer, pNdisString->Length ); }
// NDIS_STRING is UNICODE_STRING on NT but need the corresponding
// ASCII (not multi-byte ANSI) value from NDIS_STRING on any system.
// If it looks like a Unicode string then "convert" it by picking out
// every other byte, hopefully all the non-zero ones. This is not
// foolproof, but then Unicode doesn't convert to ASCII in any
// foolproof way.
//
if (pNdisString->Length > 1 && pszDup[ 1 ] == '\0') { USHORT i;
for (i = 0; i * 2 < pNdisString->Length; ++i) { pszDup[ i ] = pszDup[ i * 2 ]; }
pszDup[ i ] = '\0'; } }
return pszDup; }
CHAR* StrDupSized( IN CHAR* psz, IN ULONG ulLength, IN ULONG ulExtra )
// Return a duplicate of the first 'ulLength' bytes of 'psz' followed by a
// null character and 'ulExtra' extra bytes, or NULL on error. Caller
// must eventually call FREE_NONPAGED on the returned string.
//
{ CHAR* pszDup;
pszDup = ALLOC_NONPAGED( ulLength + 1 + ulExtra, MTAG_UTIL ); if (pszDup) { if (ulLength) { NdisMoveMemory( pszDup, psz, ulLength ); } pszDup[ ulLength ] = '\0'; }
return pszDup; }
ULONG StrLenW( IN WCHAR* psz )
// Returns number of characters in a null-terminated Unicode string.
//
{ ULONG ul;
ul = 0; while (*psz++) { ++ul; }
return ul; }
//-----------------------------------------------------------------------------
// Local utility routines (alphabetically)
//-----------------------------------------------------------------------------
ULONG atoul( IN CHAR* pszNumber )
// Convert string of digits 'pszNumber' to it's ULONG value.
//
{ ULONG ulResult;
ulResult = 0; while (*pszNumber && *pszNumber >= '0' && *pszNumber <= '9') { ulResult *= 10; ulResult += *pszNumber - '0'; ++pszNumber; }
return ulResult; }
VOID ReversePsz( IN OUT CHAR* psz )
// Reverse the order of the characters in 'psz' in place.
//
{ CHAR* pchLeft; CHAR* pchRight;
pchLeft = psz; pchRight = psz + strlen( psz ) - 1;
while (pchLeft < pchRight) { CHAR ch;
ch = *pchLeft; *pchLeft = *pchRight; *pchRight = *pchLeft; } }
#if 0
VOID ultoa( IN ULONG ul, OUT CHAR* pszBuf )
// Convert 'ul' to null-terminated string form in caller's 'pszBuf'.
//
{ CHAR* pch;
pch = pszBuf; do { *pch++ = (CHAR )((ul % 10) + '0'); ul /= 10; } while (ul); *pch = '\0';
ReversePsz( pszBuf ); } #endif
|