windows-nt/Source/XPSP1/NT/drivers/wdm/bda/ipsink/ndis/adapter.c
2020-09-26 16:20:57 +08:00

642 lines
16 KiB
C

/////////////////////////////////////////////////////////////////////////////
//
//
// Copyright (c) 1996, 1997 Microsoft Corporation
//
//
// Module Name:
// test.c
//
// Abstract:
//
// This file is a test to find out if dual binding to NDIS and KS works
//
// Author:
//
// P Porzuczek
//
// Environment:
//
// Revision History:
//
//
//////////////////////////////////////////////////////////////////////////////
#include <forward.h>
#include <memory.h>
#include <ndis.h>
#include <link.h>
#include <ipsink.h>
#include "device.h"
#include "NdisApi.h"
#include "frame.h"
#include "mem.h"
#include "adapter.h"
#include "main.h"
//////////////////////////////////////////////////////////
//
//
//
PADAPTER global_pAdapter;
UCHAR achGlobalVendorDescription [] = "Microsoft TV/Video Connection";
ULONG ulGlobalInstance = 1;
//////////////////////////////////////////////////////////
//
//
const ADAPTER_VTABLE AdapterVTable =
{
Adapter_QueryInterface,
Adapter_AddRef,
Adapter_Release,
Adapter_IndicateData,
Adapter_IndicateStatus,
Adapter_IndicateReset,
Adapter_GetDescription,
Adapter_CloseLink
};
//////////////////////////////////////////////////////////
//
//
#pragma pack (push, 1)
typedef ULONG CHECKSUM;
typedef struct _MAC_ADDRESS_
{
UCHAR Address [6];
} MAC_ADDRESS, *PMAC_ADDRESS;
typedef struct _HEADER_802_3
{
MAC_ADDRESS DestAddress;
MAC_ADDRESS SourceAddress;
UCHAR Type[2];
} HEADER_802_3, *PHEADER_802_3;
typedef struct _HEADER_IP_
{
UCHAR ucVersion_Length;
UCHAR ucTOS;
USHORT usLength;
USHORT usId;
USHORT usFlags_Offset;
UCHAR ucTTL;
UCHAR ucProtocol;
USHORT usHdrChecksum;
UCHAR ucSrcAddress [4];
UCHAR ucDestAddress [4];
} HEADER_IP, *PHEADER_IP;
#pragma pack (pop)
//////////////////////////////////////////////////////////
//
//
const HEADER_802_3 h802_3Template =
{
{0x01, 0x00, 0x5e, 0, 0, 0}
, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
, {0x08, 0x00}
};
//////////////////////////////////////////////////////////////////////////////
VOID
DumpData (
PUCHAR pData,
ULONG ulSize
)
//////////////////////////////////////////////////////////////////////////////
{
ULONG ulCount;
ULONG ul;
UCHAR uc;
while (ulSize)
{
ulCount = 16 < ulSize ? 16 : ulSize;
for (ul = 0; ul < ulCount; ul++)
{
uc = *pData;
TEST_DEBUG (TEST_DBG_TRACE, ("%02X ", uc));
ulSize -= 1;
pData += 1;
}
TEST_DEBUG (TEST_DBG_TRACE, ("\n"));
}
}
//////////////////////////////////////////////////////////////////////////////
NTSTATUS
CreateAdapter (
PADAPTER *ppAdapter,
NDIS_HANDLE ndishWrapper,
NDIS_HANDLE ndishAdapterContext
)
//////////////////////////////////////////////////////////////////////////////
{
NTSTATUS nsResult;
PADAPTER pAdapter;
UCHAR tmp_buffer [32] = {0};
//
// Init the output paramter
//
*ppAdapter = NULL;
//
// Allocate memory for the adapter block now.
//
nsResult = AllocateMemory (&pAdapter, sizeof(ADAPTER));
if (nsResult != NDIS_STATUS_SUCCESS)
{
return nsResult;
}
NdisZeroMemory (pAdapter, sizeof (ADAPTER));
//
// Init the reference count
//
pAdapter->ulRefCount = 1;
//
// Save the pAdapter into global storage
//
global_pAdapter = pAdapter;
//
// Initialize the adapter structure fields
//
pAdapter->ndishMiniport = ndishAdapterContext;
//
// Initialize the adapter vtable
//
pAdapter->lpVTable = (PADAPTER_VTABLE) &AdapterVTable;
//
// Save off the instance for this adapter
//
pAdapter->ulInstance = ulGlobalInstance++;
//
// Setup the vendor description string for this instance
//
nsResult = AllocateMemory (&pAdapter->pVendorDescription, sizeof(achGlobalVendorDescription) + 8);
if (nsResult != NDIS_STATUS_SUCCESS)
{
return nsResult;
}
NdisZeroMemory (pAdapter->pVendorDescription, sizeof (achGlobalVendorDescription) + 8);
NdisMoveMemory (pAdapter->pVendorDescription, (PVOID) achGlobalVendorDescription, sizeof (achGlobalVendorDescription));
#if DBG
MyStrCat (pAdapter->pVendorDescription, "(");
MyStrCat (pAdapter->pVendorDescription, MyUlToA (pAdapter->ulInstance, tmp_buffer, 10));
MyStrCat (pAdapter->pVendorDescription, ")");
DbgPrint ("Vendor description: %s\n", pAdapter->pVendorDescription);
#endif // DEBUG
//
// Set default completion timeout to IGNORE
//
// WARNING! The interface type is not optional!
//
NdisMSetAttributesEx (
ndishAdapterContext,
pAdapter,
4,
NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |
NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT,
NdisInterfaceInternal);
#ifndef WIN9X
//
// Create a device so other drivers (ie Streaming minidriver) can
// link up with us
//
nsResult = (NTSTATUS) ntInitializeDeviceObject (
ndishWrapper,
pAdapter,
&pAdapter->pDeviceObject,
&pAdapter->ndisDeviceHandle);
if (nsResult != NDIS_STATUS_SUCCESS)
{
return nsResult;
}
#endif
///////////////////////////////////////////////////
//
// Allocate a buffer pool. This pool will be used
// to indicate the streaming data frames.
//
CreateFramePool (pAdapter,
&pAdapter->pFramePool,
IPSINK_NDIS_MAX_BUFFERS,
IPSINK_NDIS_BUFFER_SIZE,
sizeof (IPSINK_MEDIA_SPECIFIC_INFORMATION)
);
return nsResult;
}
///////////////////////////////////////////////////////////////////////////////////
NTSTATUS
Adapter_QueryInterface (
PADAPTER pAdapter
)
///////////////////////////////////////////////////////////////////////////////////
{
return STATUS_NOT_IMPLEMENTED;
}
///////////////////////////////////////////////////////////////////////////////////
ULONG
Adapter_AddRef (
PADAPTER pAdapter
)
///////////////////////////////////////////////////////////////////////////////////
{
if (pAdapter)
{
pAdapter->ulRefCount += 1;
return pAdapter->ulRefCount;
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////////
ULONG
Adapter_Release (
PADAPTER pAdapter
)
///////////////////////////////////////////////////////////////////////////////////
{
ULONG ulRefCount = 0L;
if (pAdapter)
{
pAdapter->ulRefCount -= 1;
ulRefCount = pAdapter->ulRefCount;
if (pAdapter->ulRefCount == 0)
{
FreeMemory (pAdapter, sizeof (ADAPTER));
}
}
return ulRefCount;
}
//////////////////////////////////////////////////////////////////////////////
VOID
Adapter_IndicateReset (
PADAPTER pAdapter
)
//////////////////////////////////////////////////////////////////////////////
{
if (pAdapter)
{
if (pAdapter->pCurrentFrame != NULL)
{
if (pAdapter->pCurrentFrame->pFramePool)
{
TEST_DEBUG (TEST_DBG_TRACE, ("Putting Current Frame %08X back on Available Queue\n", pAdapter->pCurrentFrame));
PutFrame (pAdapter->pCurrentFrame->pFramePool, &pAdapter->pCurrentFrame->pFramePool->leAvailableQueue, pAdapter->pCurrentFrame);
}
pAdapter->pCurrentFrame = NULL;
pAdapter->pIn = NULL;
pAdapter->ulPR = 0;
}
}
}
//////////////////////////////////////////////////////////////////////////////
ULONG
Adapter_GetDescription (
PADAPTER pAdapter,
PUCHAR pDescription
)
//////////////////////////////////////////////////////////////////////////////
{
ULONG ulLength;
ulLength = MyStrLen (pAdapter->pVendorDescription) + 1; // add 1 to include terminator
//
// If the description pointer is NULL, then pass back the length only
//
if (pDescription != NULL)
{
NdisMoveMemory (pDescription, pAdapter->pVendorDescription, ulLength);
}
return ulLength;
}
//////////////////////////////////////////////////////////////////////////////
VOID
Adapter_CloseLink (
PADAPTER pAdapter
)
//////////////////////////////////////////////////////////////////////////////
{
if (pAdapter)
{
if (pAdapter->pFilter != NULL)
{
pAdapter->pFilter->lpVTable->Release (pAdapter->pFilter);
pAdapter->pFilter = NULL;
}
}
}
//////////////////////////////////////////////////////////////////////////////
NTSTATUS
GetNdisFrame (
PADAPTER pAdapter,
PFRAME *ppFrame
)
//////////////////////////////////////////////////////////////////////////////
{
PFRAME pFrame = NULL;
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
PHEADER_802_3 pEthHeader = NULL;
PHEADER_IP pIPHeader = NULL;
*ppFrame = NULL;
pFrame = GetFrame (pAdapter->pFramePool, &pAdapter->pFramePool->leAvailableQueue);
TEST_DEBUG (TEST_DBG_TRACE, ("Getting Frame %08X from the Available Queue\n", pFrame));
if (pFrame)
{
ntStatus = STATUS_SUCCESS;
*ppFrame = pFrame;
}
return ntStatus;
}
#define SWAP_WORD(A) ((A >> 8) & 0x00FF) + ((A << 8) & 0xFF00)
//////////////////////////////////////////////////////////////////////////////
USHORT
sizeof_packet (
PHEADER_IP pIpHdr
)
//////////////////////////////////////////////////////////////////////////////
{
USHORT usLength;
usLength = pIpHdr->usLength;
usLength = SWAP_WORD (usLength);
return usLength;
}
//////////////////////////////////////////////////////////////////////////////
NTSTATUS
TranslateAndIndicate (
PADAPTER pAdapter,
PUCHAR pOut,
ULONG ulSR
)
//////////////////////////////////////////////////////////////////////////////
{
NTSTATUS nsResult = STATUS_SUCCESS;
ULONG ulAmtToCopy;
ULONG uliNextByte;
ASSERT (pAdapter);
ASSERT (pOut);
for ( uliNextByte = 0; uliNextByte < ulSR; )
{
HEADER_802_3 * pHeader802_3;
HEADER_IP * pHeaderIP;
ulAmtToCopy = 0;
// If there is no current frame then sync up to a new
// 802.3 (RFC 894) ethernet frame.
//
if (pAdapter->pCurrentFrame == NULL)
{
// Sync to a valid looking 802.3 frame
//
while ((ulSR - uliNextByte) >= (sizeof (HEADER_802_3) + sizeof (HEADER_IP)))
{
pHeader802_3 = (HEADER_802_3 *) &(pOut[uliNextByte]);
pHeaderIP = (HEADER_IP *) &(pOut[uliNextByte + sizeof(HEADER_802_3)]);
if ( (pHeader802_3->Type[0] == 0x08)
&& (pHeader802_3->Type[1] == 0x00)
&& (pHeaderIP->ucVersion_Length == 0x45)
&& (sizeof_packet( pHeaderIP) <= MAX_IP_PACKET_SIZE)
)
{
break;
}
uliNextByte++;
}
if ((ulSR - uliNextByte) < (sizeof (HEADER_802_3) + sizeof (HEADER_IP)))
{
TEST_DEBUG (TEST_DBG_INFO, ("Stream buffer consumed while searching for valid IP packet\n"));
nsResult = STATUS_SUCCESS;
goto ret;
}
//
// Everything looks good...get a new frame and start data transfer
//
nsResult = GetNdisFrame( pAdapter,
&pAdapter->pCurrentFrame
);
if (nsResult != STATUS_SUCCESS)
{
TEST_DEBUG (TEST_DBG_ERROR, ("Get NDIS frame failed. No more NDIS frames available. No Frame built\n"));
nsResult = STATUS_SUCCESS;
pAdapter->stats.ulOID_GEN_RCV_NO_BUFFER += 1;
pAdapter->pIn = NULL;
pAdapter->pCurrentFrame = NULL;
pAdapter->ulPR = 0;
goto ret;
}
//
// Update the reference count for this frame
//
pAdapter->pCurrentFrame->lpVTable->AddRef( pAdapter->pCurrentFrame);
//
// define pointers to the data in and out buffers, and init the packet size field
//
pAdapter->pIn = (PUCHAR) (pAdapter->pCurrentFrame->pvMemory);
pAdapter->ulPR = sizeof_packet( pHeaderIP) + sizeof (HEADER_802_3);
pAdapter->pCurrentFrame->ulcbData = pAdapter->ulPR;
TEST_DEBUG (TEST_DBG_TRACE, ("CREATING NEW NDIS FRAME %08X, packet size %d\n", pAdapter->pCurrentFrame, pAdapter->ulPR));
}
if (pAdapter->ulPR <= (ulSR - uliNextByte))
{
ulAmtToCopy = pAdapter->ulPR;
}
else
{
ulAmtToCopy = ulSR - uliNextByte;
}
NdisMoveMemory( pAdapter->pIn,
&(pOut[uliNextByte]),
ulAmtToCopy
);
pAdapter->pIn += ulAmtToCopy;
pAdapter->ulPR -= ulAmtToCopy;
uliNextByte += ulAmtToCopy;
if (pAdapter->ulPR == 0)
{
BOOLEAN bResult;
PINDICATE_CONTEXT pIndicateContext = NULL;
NDIS_HANDLE SwitchHandle = NULL;
AllocateMemory (&pIndicateContext, sizeof (INDICATE_CONTEXT));
if(!pIndicateContext)
{
nsResult = STATUS_NO_MEMORY;
goto ret;
}
pIndicateContext->pAdapter = pAdapter;
//
// Place the frame on the indicateQueue
//
TEST_DEBUG (TEST_DBG_TRACE, ("Putting Frame %08X on Indicate Queue\n", pAdapter->pCurrentFrame));
PutFrame (pAdapter->pFramePool, &pAdapter->pFramePool->leIndicateQueue, pAdapter->pCurrentFrame);
pAdapter->pCurrentFrame = NULL;
//
//
// Switch to a state which allows us to call NDIS functions
//
bResult = NdisIMSwitchToMiniport (pAdapter->ndishMiniport, &SwitchHandle);
if (bResult == TRUE)
{
nsResult = IndicateCallbackHandler (pAdapter->ndishMiniport, (PVOID) pIndicateContext);
NdisIMRevertBack (pAdapter->ndishMiniport, SwitchHandle);
}
else
{
nsResult = NdisIMQueueMiniportCallback (pAdapter->ndishMiniport, IndicateCallbackHandler, (PVOID) pIndicateContext);
}
}
}
ret:
return nsResult;
}
//////////////////////////////////////////////////////////////////////////////
NTSTATUS
Adapter_IndicateData (
IN PADAPTER pAdapter,
IN PVOID pvData,
IN ULONG ulcbData
)
//////////////////////////////////////////////////////////////////////////////
{
NTSTATUS ntStatus = STATUS_SUCCESS;
ntStatus = TranslateAndIndicate (pAdapter, pvData, ulcbData);
return ntStatus;
}
//////////////////////////////////////////////////////////////////////////////
NTSTATUS
Adapter_IndicateStatus (
IN PADAPTER pAdapter,
IN PVOID pvEvent
)
//////////////////////////////////////////////////////////////////////////////
{
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
BOOLEAN bResult = FALSE;
NDIS_HANDLE SwitchHandle = NULL;
//
// Switch to a state which allows us to call NDIS functions
//
bResult = NdisIMSwitchToMiniport (pAdapter, &SwitchHandle);
if (bResult == TRUE)
{
//ntStatus = IndicateEvent (pAdapter, pvEvent);
//
// Revert back to previous state
//
NdisIMRevertBack (pAdapter, SwitchHandle);
ntStatus = STATUS_SUCCESS;
goto ret;
}
else
{
// Queue a miniport callback
}
ret:
return ntStatus;
}