mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
816 lines
19 KiB
816 lines
19 KiB
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
send.c
|
|
|
|
Abstract:
|
|
|
|
This file contains the code for putting a packet through the
|
|
staged allocation for transmission.
|
|
|
|
This is a process of
|
|
|
|
1) Calculating the what would need to be done to the
|
|
packet so that the packet can be transmitted on the hardware.
|
|
|
|
2) Potentially allocating adapter buffers and copying user data
|
|
to those buffers so that the packet data is transmitted under
|
|
the hardware constraints.
|
|
|
|
3) Allocating enough hardware ring entries so that the packet
|
|
can be transmitted.
|
|
|
|
4) Relinquish those ring entries to the hardware.
|
|
|
|
Author:
|
|
|
|
Anthony V. Ercolano (Tonye) 12-Sept-1990
|
|
Keith Moore (KeithMo) 08-Jan-1991
|
|
|
|
Environment:
|
|
|
|
Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include <ne3200sw.h>
|
|
|
|
//
|
|
// Forward declarations of functions in this file.
|
|
//
|
|
VOID
|
|
NE3200ConstrainPacket(
|
|
IN PNE3200_ADAPTER Adapter,
|
|
IN PNDIS_PACKET Packet
|
|
);
|
|
|
|
NDIS_STATUS
|
|
NE3200TransmitPacket(
|
|
IN PNE3200_ADAPTER Adapter,
|
|
PNDIS_PACKET FirstPacket,
|
|
UINT TotalDataLength,
|
|
UINT NdisBufferCount,
|
|
PNDIS_BUFFER CurrentBuffer
|
|
);
|
|
|
|
NDIS_STATUS
|
|
NE3200TransmitMergedPacket(
|
|
IN PNE3200_ADAPTER Adapter,
|
|
PNDIS_PACKET FirstPacket
|
|
);
|
|
|
|
|
|
NDIS_STATUS
|
|
NE3200Send(
|
|
IN NDIS_HANDLE MiniportAdapterContext,
|
|
IN PNDIS_PACKET Packet,
|
|
IN UINT Flags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The NE3200Send request instructs a Miniport to transmit a packet through
|
|
the adapter onto the medium.
|
|
|
|
Arguments:
|
|
|
|
MiniportAdapterContext - The context value returned by the Miniport when the
|
|
adapter was initialized. In reality, it is a pointer to NE3200_ADAPTER.
|
|
|
|
Packet - A pointer to a descriptor for the packet that is to be
|
|
transmitted.
|
|
|
|
Flags - The send options to use.
|
|
|
|
Return Value:
|
|
|
|
The function value is the status of the operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Pointer to the adapter.
|
|
//
|
|
PNE3200_ADAPTER Adapter;
|
|
|
|
//
|
|
// The number of physical buffers in the entire packet.
|
|
//
|
|
UINT PhysicalBufferCount;
|
|
|
|
//
|
|
// The total amount of data in the ndis packet.
|
|
//
|
|
UINT TotalDataLength;
|
|
|
|
//
|
|
// The number of ndis buffers in the packet.
|
|
//
|
|
UINT NdisBufferCount;
|
|
|
|
//
|
|
// Points to the current ndis buffer being walked.
|
|
//
|
|
PNDIS_BUFFER CurrentBuffer;
|
|
|
|
//
|
|
// Points to the miniport reserved portion of this packet. This
|
|
// interpretation of the reserved section is only valid during
|
|
// the allocation phase of the packet.
|
|
//
|
|
PNE3200_RESERVED Reserved = PNE3200_RESERVED_FROM_PACKET(Packet);
|
|
|
|
//
|
|
// Status of the transmit.
|
|
//
|
|
NDIS_STATUS Status;
|
|
|
|
//
|
|
// The adapter upon which to transmit the packet.
|
|
//
|
|
Adapter = PNE3200_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
|
|
|
|
IF_LOG('s');
|
|
|
|
//
|
|
// Check if this is a packet we rejected earlier due to a lack
|
|
// of resources. If so, we don't have to recalculate all the
|
|
// constraints.
|
|
//
|
|
if (!Adapter->PacketResubmission) {
|
|
|
|
ASSERT(sizeof(NE3200_RESERVED) <= sizeof(Packet->MiniportReserved));
|
|
|
|
//
|
|
// Determine if and how much adapter space would need to be allocated
|
|
// to meet hardware constraints.
|
|
//
|
|
NdisQueryPacket(
|
|
Packet,
|
|
&PhysicalBufferCount,
|
|
&NdisBufferCount,
|
|
&CurrentBuffer,
|
|
&TotalDataLength
|
|
);
|
|
|
|
|
|
//
|
|
// See if the packet exceeds NE3200_MAXIMUM_BLOCKS_PER_PACKET.
|
|
// Keep in mind that if the total virtual packet length is less than
|
|
// MINIMUM_ETHERNET_PACKET_SIZE then we'll have to chain on an
|
|
// additional buffer to pad the packet out to the minimum size.
|
|
//
|
|
if ( PhysicalBufferCount < NE3200_MAXIMUM_BLOCKS_PER_PACKET ) {
|
|
|
|
//
|
|
// This packet will not need a merge buffer
|
|
//
|
|
Reserved->UsedNE3200Buffer = FALSE;
|
|
|
|
//
|
|
// See if we can send it now.
|
|
//
|
|
Status = NE3200TransmitPacket(
|
|
Adapter,
|
|
Packet,
|
|
TotalDataLength,
|
|
NdisBufferCount,
|
|
CurrentBuffer
|
|
);
|
|
|
|
Adapter->PacketResubmission =
|
|
(BOOLEAN)(Status == NDIS_STATUS_RESOURCES);
|
|
|
|
IF_LOG('S');
|
|
|
|
return(Status);
|
|
|
|
} else {
|
|
|
|
//
|
|
// We will have to use a merge buffer. Let the processing
|
|
// below handle this.
|
|
//
|
|
if ( (PhysicalBufferCount > NE3200_MAXIMUM_BLOCKS_PER_PACKET) ||
|
|
(TotalDataLength < MINIMUM_ETHERNET_PACKET_SIZE) ) {
|
|
|
|
Reserved->UsedNE3200Buffer = TRUE;
|
|
|
|
} else {
|
|
|
|
Reserved->UsedNE3200Buffer = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Check if we have to merge this packet.
|
|
//
|
|
if ( Reserved->UsedNE3200Buffer ) {
|
|
|
|
//
|
|
// Try and send it now.
|
|
//
|
|
Status = NE3200TransmitMergedPacket(Adapter, Packet);
|
|
|
|
} else {
|
|
|
|
//
|
|
// Determine if and how much adapter space would need to be allocated
|
|
// to meet hardware constraints.
|
|
//
|
|
|
|
NdisQueryPacket(
|
|
Packet,
|
|
NULL,
|
|
&NdisBufferCount,
|
|
&CurrentBuffer,
|
|
&TotalDataLength
|
|
);
|
|
|
|
|
|
Status = NE3200TransmitPacket(
|
|
Adapter,
|
|
Packet,
|
|
TotalDataLength,
|
|
NdisBufferCount,
|
|
CurrentBuffer);
|
|
|
|
}
|
|
|
|
//
|
|
// Save if this packet was rejected due to lack of resources.
|
|
//
|
|
Adapter->PacketResubmission = (BOOLEAN)(Status == NDIS_STATUS_RESOURCES);
|
|
|
|
IF_LOG('S');
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
//
|
|
// Put this code inline to save the overhead of the function call.
|
|
//
|
|
#ifdef _X86_
|
|
__inline
|
|
#endif
|
|
|
|
NDIS_STATUS
|
|
NE3200TransmitPacket(
|
|
IN PNE3200_ADAPTER Adapter,
|
|
PNDIS_PACKET FirstPacket,
|
|
UINT TotalDataLength,
|
|
UINT NdisBufferCount,
|
|
PNDIS_BUFFER CurrentBuffer
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine attempts to take a packet through a stage of allocation
|
|
and transmit it.
|
|
|
|
Arguments:
|
|
|
|
Adapter - The adapter that the packets are coming through.
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_RESOURCES - if there are not enough resources
|
|
NDIS_STATUS_PENDING - if sending.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// If we successfully acquire a command block, this
|
|
// is a pointer to it.
|
|
//
|
|
PNE3200_SUPER_COMMAND_BLOCK CommandBlock;
|
|
|
|
//
|
|
// Pointer to the NE3200 data block descriptor being filled.
|
|
//
|
|
PNE3200_DATA_BLOCK DataBlock;
|
|
|
|
//
|
|
// Array to hold the physical segments
|
|
//
|
|
NDIS_PHYSICAL_ADDRESS_UNIT PhysicalSegmentArray[NE3200_MAXIMUM_BLOCKS_PER_PACKET];
|
|
|
|
//
|
|
// Number of physical segments in the buffer
|
|
//
|
|
UINT BufferPhysicalSegments;
|
|
|
|
//
|
|
// map register to use for this buffer
|
|
//
|
|
UINT CurMapRegister;
|
|
|
|
//
|
|
// Iteration variable
|
|
//
|
|
UINT i;
|
|
|
|
//
|
|
// We look to see if there is an available Command Block.
|
|
// If there isn't then stage 3 will close.
|
|
//
|
|
|
|
NE3200AcquireCommandBlock(
|
|
Adapter,
|
|
&CommandBlock
|
|
);
|
|
|
|
if (CommandBlock != NULL) {
|
|
|
|
//
|
|
// We have a command block. Assign all packet
|
|
// buffers to the command block.
|
|
//
|
|
|
|
//
|
|
// Get a pointer to the the first data block descriptor
|
|
// in the Command Block.
|
|
//
|
|
DataBlock = &CommandBlock->Hardware.TransmitDataBlocks[0];
|
|
|
|
//
|
|
// We record the owning packet information in the ring packet packet
|
|
// structure.
|
|
//
|
|
CommandBlock->OwningPacket = FirstPacket;
|
|
CommandBlock->UsedNE3200Buffer = FALSE;
|
|
CommandBlock->NextCommand = NULL;
|
|
|
|
//
|
|
// Initialize the various fields of the Command Block.
|
|
//
|
|
CommandBlock->Hardware.State = NE3200_STATE_WAIT_FOR_ADAPTER;
|
|
CommandBlock->Hardware.Status = 0;
|
|
CommandBlock->Hardware.NextPending = NE3200_NULL;
|
|
CommandBlock->Hardware.CommandCode = NE3200_COMMAND_TRANSMIT;
|
|
CommandBlock->Hardware.PARAMETERS.TRANSMIT.ImmediateDataLength = 0;
|
|
|
|
CommandBlock->Hardware.NumberOfDataBlocks = 0;
|
|
CommandBlock->Hardware.TransmitFrameSize = (USHORT)TotalDataLength;
|
|
|
|
//
|
|
// Set the map registers to use
|
|
//
|
|
CurMapRegister = CommandBlock->CommandBlockIndex *
|
|
NE3200_MAXIMUM_BLOCKS_PER_PACKET;
|
|
|
|
//
|
|
// Go through all of the buffers in the packet getting
|
|
// the actual physical buffers from each NDIS_BUFFER.
|
|
//
|
|
do {
|
|
|
|
NdisMStartBufferPhysicalMapping(
|
|
Adapter->MiniportAdapterHandle,
|
|
CurrentBuffer,
|
|
CurMapRegister,
|
|
TRUE,
|
|
PhysicalSegmentArray,
|
|
&BufferPhysicalSegments
|
|
);
|
|
|
|
//
|
|
// Go to the next map register
|
|
//
|
|
CurMapRegister++;
|
|
|
|
//
|
|
// Store segments into command block
|
|
//
|
|
for (i = 0; i < BufferPhysicalSegments ; i++, DataBlock++ ) {
|
|
|
|
DataBlock->BlockLength = (USHORT)PhysicalSegmentArray[i].Length;
|
|
DataBlock->PhysicalAddress = NdisGetPhysicalAddressLow(PhysicalSegmentArray[i].PhysicalAddress);
|
|
|
|
}
|
|
|
|
//
|
|
// Update the number of fragments.
|
|
//
|
|
CommandBlock->Hardware.NumberOfDataBlocks += BufferPhysicalSegments;
|
|
|
|
NdisFlushBuffer(CurrentBuffer, TRUE);
|
|
|
|
//
|
|
// Go to the next buffer.
|
|
//
|
|
NdisGetNextBuffer(
|
|
CurrentBuffer,
|
|
&CurrentBuffer
|
|
);
|
|
|
|
} while (CurrentBuffer != NULL);
|
|
|
|
//
|
|
// If the total packet length is less than MINIMUM_ETHERNET_PACKET_SIZE
|
|
// then we must chain the Padding buffer onto the end and update
|
|
// the transfer size.
|
|
//
|
|
if (TotalDataLength >= MINIMUM_ETHERNET_PACKET_SIZE) {
|
|
|
|
PNE3200_RESERVED_FROM_PACKET(FirstPacket)->CommandBlockIndex =
|
|
CommandBlock->CommandBlockIndex;
|
|
|
|
IF_LOG('x');
|
|
|
|
NE3200SubmitCommandBlock(
|
|
Adapter,
|
|
CommandBlock
|
|
);
|
|
|
|
return(NDIS_STATUS_PENDING);
|
|
}
|
|
|
|
//
|
|
// Must do padding
|
|
//
|
|
DataBlock->BlockLength =
|
|
(USHORT)(MINIMUM_ETHERNET_PACKET_SIZE - TotalDataLength);
|
|
|
|
DataBlock->PhysicalAddress = NdisGetPhysicalAddressLow(Adapter->PaddingPhysicalAddress);
|
|
|
|
DataBlock++;
|
|
CommandBlock->Hardware.NumberOfDataBlocks++;
|
|
|
|
CommandBlock->Hardware.TransmitFrameSize = MINIMUM_ETHERNET_PACKET_SIZE;
|
|
|
|
PNE3200_RESERVED_FROM_PACKET(FirstPacket)->CommandBlockIndex =
|
|
CommandBlock->CommandBlockIndex;
|
|
|
|
IF_LOG('x');
|
|
|
|
NE3200SubmitCommandBlock(
|
|
Adapter,
|
|
CommandBlock
|
|
);
|
|
|
|
return(NDIS_STATUS_PENDING);
|
|
|
|
} else {
|
|
|
|
//
|
|
// Not enough resources
|
|
//
|
|
return(NDIS_STATUS_RESOURCES);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
NE3200TransmitMergedPacket(
|
|
IN PNE3200_ADAPTER Adapter,
|
|
PNDIS_PACKET FirstPacket
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine attempts to take a packet through a stage of allocation
|
|
and tranmit it. The packet needs to be merged into a single
|
|
before transmitting because it contains more fragments than the
|
|
adapter can handle.
|
|
|
|
Arguments:
|
|
|
|
Adapter - The adapter that the packets are coming through.
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_RESOURCES - if there are not enough resources
|
|
NDIS_STATUS_PENDING - if sending.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// If we successfully acquire a command block, this
|
|
// is a pointer to it.
|
|
//
|
|
PNE3200_SUPER_COMMAND_BLOCK CommandBlock;
|
|
|
|
//
|
|
// Points to the reserved portion of the packet.
|
|
//
|
|
PNE3200_RESERVED Reserved;
|
|
|
|
//
|
|
// Pointer to the NE3200 data block descriptor being filled.
|
|
//
|
|
PNE3200_DATA_BLOCK DataBlock;
|
|
|
|
//
|
|
// Points to the adapter buffer descriptor allocated
|
|
// for this packet.
|
|
//
|
|
PNE3200_BUFFER_DESCRIPTOR BufferDescriptor;
|
|
|
|
//
|
|
// Check that we have a merge buffer if one will be necessary.
|
|
//
|
|
if ( Adapter->NE3200BufferListHead == -1 ) {
|
|
|
|
//
|
|
// Not enough space for the packet -- save state
|
|
//
|
|
return NDIS_STATUS_RESOURCES;
|
|
|
|
}
|
|
|
|
//
|
|
// We look to see if there is an available Command Block.
|
|
// If there isn't then stage 3 will close.
|
|
//
|
|
NE3200AcquireCommandBlock(
|
|
Adapter,
|
|
&CommandBlock
|
|
);
|
|
|
|
if (CommandBlock != NULL) {
|
|
|
|
//
|
|
// We have a command block. Assign all packet
|
|
// buffers to the command block.
|
|
//
|
|
Reserved = PNE3200_RESERVED_FROM_PACKET(FirstPacket);
|
|
|
|
//
|
|
// Get a pointer to the the first data block descriptor
|
|
// in the Command Block.
|
|
//
|
|
DataBlock = &CommandBlock->Hardware.TransmitDataBlocks[0];
|
|
|
|
//
|
|
// Now we merge the packet into a buffer
|
|
//
|
|
NE3200ConstrainPacket(Adapter, FirstPacket);
|
|
|
|
//
|
|
// We record the owning packet information in the ring packet packet
|
|
// structure.
|
|
//
|
|
CommandBlock->OwningPacket = FirstPacket;
|
|
CommandBlock->UsedNE3200Buffer = TRUE;
|
|
CommandBlock->NE3200BuffersIndex = Reserved->NE3200BuffersIndex;
|
|
CommandBlock->NextCommand = NULL;
|
|
|
|
//
|
|
// Initialize the various fields of the Command Block.
|
|
//
|
|
CommandBlock->Hardware.State = NE3200_STATE_WAIT_FOR_ADAPTER;
|
|
CommandBlock->Hardware.Status = 0;
|
|
CommandBlock->Hardware.NextPending = NE3200_NULL;
|
|
CommandBlock->Hardware.CommandCode = NE3200_COMMAND_TRANSMIT;
|
|
CommandBlock->Hardware.PARAMETERS.TRANSMIT.ImmediateDataLength = 0;
|
|
|
|
//
|
|
// Get the buffer descriptor
|
|
//
|
|
BufferDescriptor = Adapter->NE3200Buffers + Reserved->NE3200BuffersIndex;
|
|
|
|
//
|
|
// Since this packet used one of the adapter buffers, the
|
|
// following is known:
|
|
//
|
|
// o There is exactly one physical buffer for this packet.
|
|
// o The buffer's length is the transmit frame size.
|
|
//
|
|
|
|
//
|
|
// Set the number of data blocks and the transmit frame size.
|
|
//
|
|
NdisFlushBuffer(BufferDescriptor->FlushBuffer, TRUE);
|
|
CommandBlock->Hardware.NumberOfDataBlocks = 1;
|
|
CommandBlock->Hardware.TransmitFrameSize =
|
|
(USHORT)BufferDescriptor->DataLength;
|
|
|
|
//
|
|
// Initialize the (one) data block for this transmit.
|
|
//
|
|
DataBlock->BlockLength = (USHORT)BufferDescriptor->DataLength;
|
|
DataBlock->PhysicalAddress = NdisGetPhysicalAddressLow(BufferDescriptor->PhysicalNE3200Buffer);
|
|
|
|
Adapter->TransmitsQueued++;
|
|
|
|
Reserved->CommandBlockIndex = CommandBlock->CommandBlockIndex;
|
|
|
|
IF_LOG('x');
|
|
|
|
//
|
|
// Start the transmit.
|
|
//
|
|
NE3200SubmitCommandBlock(
|
|
Adapter,
|
|
CommandBlock
|
|
);
|
|
|
|
return(NDIS_STATUS_PENDING);
|
|
}
|
|
|
|
return(NDIS_STATUS_RESOURCES);
|
|
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
NE3200ConstrainPacket(
|
|
IN PNE3200_ADAPTER Adapter,
|
|
IN PNDIS_PACKET Packet
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given a packet and if necessary attempt to acquire adapter
|
|
buffer resources so that the packet meets NE3200 hardware/MAC.BIN
|
|
contraints.
|
|
|
|
NOTE : MUST BE CALLED WITH NE3200BufferListHead != -1!!
|
|
|
|
Arguments:
|
|
|
|
Adapter - The adapter the packet is coming through.
|
|
|
|
Packet - The packet whose buffers are to be constrained.
|
|
The packet reserved section is filled with information
|
|
detailing how the packet needs to be adjusted.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Holds the adapter buffer index available for allocation.
|
|
//
|
|
INT NE3200BuffersIndex;
|
|
|
|
//
|
|
// Points to a successfully allocated adapter buffer descriptor.
|
|
//
|
|
PNE3200_BUFFER_DESCRIPTOR BufferDescriptor;
|
|
|
|
//
|
|
// Will point into the virtual address space addressed
|
|
// by the adapter buffer if one was successfully allocated.
|
|
//
|
|
PCHAR CurrentDestination;
|
|
|
|
//
|
|
// Will hold the total amount of data copied to the
|
|
// adapter buffer.
|
|
//
|
|
UINT TotalDataMoved = 0;
|
|
|
|
//
|
|
// Will point to the current source buffer.
|
|
//
|
|
PNDIS_BUFFER SourceBuffer;
|
|
|
|
//
|
|
// Points to the virtual address of the source buffers data.
|
|
//
|
|
PVOID SourceData;
|
|
|
|
//
|
|
// The number of ndis buffers in the packet.
|
|
//
|
|
UINT NdisBufferCount;
|
|
|
|
//
|
|
// Will point to the number of bytes of data in the source
|
|
// buffer.
|
|
//
|
|
UINT SourceLength;
|
|
|
|
//
|
|
// The total amount of data contained within the ndis packet.
|
|
//
|
|
UINT TotalVirtualLength;
|
|
|
|
//
|
|
// Simple iteration variable.
|
|
//
|
|
INT i;
|
|
|
|
NE3200BuffersIndex = Adapter->NE3200BufferListHead;
|
|
|
|
BufferDescriptor = Adapter->NE3200Buffers + NE3200BuffersIndex;
|
|
Adapter->NE3200BufferListHead = BufferDescriptor->Next;
|
|
|
|
//
|
|
// Fill in the adapter buffer with the data from the users
|
|
// buffers.
|
|
//
|
|
CurrentDestination = BufferDescriptor->VirtualNE3200Buffer;
|
|
|
|
NdisQueryPacket(
|
|
Packet,
|
|
NULL,
|
|
&NdisBufferCount,
|
|
&SourceBuffer,
|
|
&TotalVirtualLength
|
|
);
|
|
|
|
NdisQueryBuffer(
|
|
SourceBuffer,
|
|
&SourceData,
|
|
&SourceLength
|
|
);
|
|
|
|
BufferDescriptor->DataLength = TotalVirtualLength;
|
|
|
|
for (
|
|
i = NdisBufferCount;
|
|
i;
|
|
i--
|
|
) {
|
|
|
|
//
|
|
// Copy this buffer
|
|
//
|
|
NE3200_MOVE_MEMORY(
|
|
CurrentDestination,
|
|
SourceData,
|
|
SourceLength
|
|
);
|
|
|
|
//
|
|
// Update destination address
|
|
//
|
|
CurrentDestination = (PCHAR)CurrentDestination + SourceLength;
|
|
|
|
//
|
|
// Update count of packet length.
|
|
//
|
|
TotalDataMoved += SourceLength;
|
|
|
|
if (i > 1) {
|
|
|
|
//
|
|
// Get the next buffers information
|
|
//
|
|
NdisGetNextBuffer(
|
|
SourceBuffer,
|
|
&SourceBuffer
|
|
);
|
|
|
|
NdisQueryBuffer(
|
|
SourceBuffer,
|
|
&SourceData,
|
|
&SourceLength
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// If the packet is less than the minimum Ethernet
|
|
// packet size, then clear the remaining part of
|
|
// the buffer up to the minimum packet size.
|
|
//
|
|
if (TotalVirtualLength < MINIMUM_ETHERNET_PACKET_SIZE) {
|
|
|
|
NdisZeroMemory(
|
|
CurrentDestination,
|
|
MINIMUM_ETHERNET_PACKET_SIZE - TotalVirtualLength
|
|
);
|
|
|
|
}
|
|
|
|
//
|
|
// We need to save in the packet which adapter buffer descriptor
|
|
// it is using so that we can deallocate it later.
|
|
//
|
|
PNE3200_RESERVED_FROM_PACKET(Packet)->NE3200BuffersIndex = NE3200BuffersIndex;
|
|
}
|
|
|