Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

875 lines
20 KiB

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
mlidsend.c
Abstract:
This file contains all routines for sending packets.
Author:
Sean Selitrennikoff (SeanSe) 3-8-93
Environment:
Kernel Mode.
Revision History:
--*/
#include <ndis.h>
#include "lsl.h"
#include "frames.h"
#include "mlid.h"
#include "ndismlid.h"
VOID
NdisMlidBuildMediaHeader(
PMLID_STRUCT Mlid,
PMLID_RESERVED Reserved,
UINT32 FrameLength,
PUINT8 DestinationAddress,
PUINT8 ProtocolID
);
VOID
SendPackets(
PMLID_STRUCT Mlid
)
/*++
Routine Description:
This routine is called whenever there is a need to send a packet. It will
take as many Send ECBs from the Mlid as possible and convert them into NDIS_PACKETS
and submit them to the NDIS_MAC.
NOTE: This must be called with Mlid->StageOpen = TRUE;
NOTE: This must be called with Mlid->InSendPacket = FALSE;
NOTE: Called with Mlid->MlidSpinLock held!!
Arguments:
Mlid - Pointer to the MLID_STRUCT to service.
Return Value:
None.
--*/
{
PNDIS_PACKET NdisSendPacket;
PNDIS_BUFFER NdisBuffer;
PMLID_RESERVED Reserved;
UINT32 i;
BOOLEAN HeldEvents = FALSE;
NDIS_STATUS NdisStatus;
PECB SendECB;
ASSERT(Mlid->StageOpen == TRUE);
ASSERT(Mlid->InSendPacket == FALSE);
//
// While there any sends queued
//
while (Mlid->FirstPendingSend) {
//
// If there are no NDIS_PACKETs avaiable, then close stage and exit.
//
NdisAllocatePacket(
&NdisStatus,
&NdisSendPacket,
Mlid->SendPacketPool
);
if (NdisStatus != NDIS_STATUS_SUCCESS) {
Mlid->StageOpen = FALSE;
break;
}
Reserved = PMLID_RESERVED_FROM_PNDIS_PACKET(NdisSendPacket);
//
// Initialize NDIS_PACKET
//
NdisReinitializePacket(NdisSendPacket);
SendECB = Mlid->FirstPendingSend;
//
// Convert ECB fragment list into an MDL chain
//
for (i = 0; i < SendECB->ECB_FragmentCount; i++) {
NdisAllocateBuffer(
&NdisStatus,
&NdisBuffer,
Mlid->SendBufferPool,
SendECB->ECB_Fragment[i].FragmentAddress,
SendECB->ECB_Fragment[i].FragmentLength
);
if (NdisStatus != NDIS_STATUS_SUCCESS) {
goto Fail1;
}
NdisChainBufferAtBack(
NdisSendPacket,
NdisBuffer
);
}
//
// Build the media header
//
NdisMlidBuildMediaHeader(Mlid,
Reserved,
SendECB->ECB_DataLength,
SendECB->ECB_ImmediateAddress,
SendECB->ECB_ProtocolID
);
//
// Link media header into front of MDL chain
//
NdisAllocateBuffer(
&NdisStatus,
&NdisBuffer,
Mlid->SendBufferPool,
Reserved->MediaHeader,
Reserved->MediaHeaderLength
);
if (NdisStatus != NDIS_STATUS_SUCCESS) {
goto Fail1;
}
NdisChainBufferAtFront(
NdisSendPacket,
NdisBuffer
);
//
// Remove Send ECB from Send Queue
//
Mlid->FirstPendingSend = SendECB->ECB_NextLink;
if (Mlid->LastPendingSend == SendECB) {
Mlid->LastPendingSend = NULL;
} else {
SendECB->ECB_NextLink->ECB_PreviousLink = NULL;
}
//
// Store ECB in reserved section
//
Reserved->SendECB = SendECB;
//
// Release MlidSpinLock
//
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
//
// Submit to NDIS_MAC
//
NdisSend(
&NdisStatus,
Mlid->NdisBindingHandle,
NdisSendPacket
);
//
// Acquire MlidSpinLock
//
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
//
// If not pending, then
//
if (NdisStatus != NDIS_STATUS_PENDING) {
//
// Return resources to Mlid
//
NdisUnchainBufferAtFront(
NdisSendPacket,
&NdisBuffer
);
while (NdisBuffer != NULL) {
NdisFreeBuffer(NdisBuffer);
NdisUnchainBufferAtFront(
NdisSendPacket,
&NdisBuffer
);
}
NdisFreePacket(NdisSendPacket);
//
// Store completion status in ECB
//
if (NdisStatus == NDIS_STATUS_SUCCESS) {
SendECB->ECB_Status = (UINT16)SUCCESSFUL;
} else {
SendECB->ECB_Status = (UINT16)FAIL;
}
//
// Release MlidSpinLock
//
NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
//
// put ECB on LSLEventQueue
//
(*(Mlid->LSLFunctionList->SupportAPIArray[HoldEvent_INDEX]))(
SendECB
);
//
// Acquire MlidSpinLock
//
NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
//
// Set flag to service events
//
HeldEvents = TRUE;
}
}
//
// Call LSL_ServiceEvents if necessary
//
if (HeldEvents) {
(*(Mlid->LSLFunctionList->SupportAPIArray[ServiceEvents_INDEX]))(
);
}
return;
Fail1:
//
// Unchain all NDIS_BUFFERs from packet
//
NdisUnchainBufferAtFront(
NdisSendPacket,
&NdisBuffer
);
while (NdisBuffer != NULL) {
NdisFreeBuffer(NdisBuffer);
NdisUnchainBufferAtFront(
NdisSendPacket,
&NdisBuffer
);
}
//
// Return NDIS_PACKET
//
NdisFreePacket(NdisSendPacket);
//
// Close stage
//
Mlid->StageOpen = FALSE;
return;
}
VOID
ReturnSendPacketResources(
PNDIS_PACKET Packet
)
/*++
Routine Description:
This routine is called to return the MLID resources allocated for a sent NDIS_PACKET.
This includes the entire MDL chain itself and the NDIS_PACKET.
NOTE: Called with Mlid->MlidSpinLock held!!
Arguments:
Packet - Pointer to the NDIS_PACKET to free.
Return Value:
None.
--*/
{
PNDIS_BUFFER NdisBuffer;
//
// Unchain all NDIS_BUFFERs from packet
//
NdisUnchainBufferAtFront(
Packet,
&NdisBuffer
);
while (NdisBuffer != NULL) {
NdisFreeBuffer(NdisBuffer);
NdisUnchainBufferAtFront(
Packet,
&NdisBuffer
);
}
//
// Return NDIS_PACKET
//
NdisFreePacket(Packet);
}
VOID
NdisMlidBuildMediaHeader(
PMLID_STRUCT Mlid,
PMLID_RESERVED Reserved,
UINT32 FrameLength,
PUINT8 DestinationAddress,
PUINT8 ProtocolID
)
/*++
Routine Description:
This routine assembles a packet header for the MLID and ProtocolID given into
the given reserved section.
NOTE: Called with Mlid->MlidSpinLock held!!
Arguments:
Mlid - Pointer to MLID
Reserved - Pointer to a reserved section with memory to hold the header.
FrameLength - Length of the Data portion of the frame.
DestinationAddress - The address that the packet will be addresses to.
ProtocolID - The ID that has DSAP and other information in it.
Return Value:
None.
--*/
{
PUINT8 SourceRoutingInfo;
UINT32 SourceRoutingLength;
UINT32 DataLength = FrameLength;
PUINT8 CurrentPlace = Reserved->MediaHeader;
//
// Switch on media type
//
switch (Mlid->NdisMlidMedium) {
case NdisMedium802_5:
if (Mlid->ConfigTable.MLIDCFG_SourceRouting != NULL) {
//
// Get any source routing information
//*\\ Get SR Info. Are parameters correct?
SourceRoutingInfo = (*((PLSL_SR_FUNCTION)(Mlid->ConfigTable.MLIDCFG_SourceRouting)))
( Mlid->BoardNumber,
&SourceRoutingLength,
DestinationAddress
);
}
//
// Set AC field
//
*CurrentPlace = 0x10;
CurrentPlace++;
//
// Set FC field
//
*CurrentPlace = 0x40;
CurrentPlace++;
//
// Set DestinationAddress
//
RtlCopyMemory(CurrentPlace, DestinationAddress, 6);
CurrentPlace += 6;
//
// Set SourceAddress
//
RtlCopyMemory(CurrentPlace, Mlid->ConfigTable.MLIDCFG_NodeAddress, 6);
CurrentPlace += 6;
//
// Copy SourceRoutingInfo
//
RtlCopyMemory(CurrentPlace, SourceRoutingInfo, SourceRoutingLength);
CurrentPlace += SourceRoutingLength;
//
// Switch on frame type
//
switch (Mlid->ConfigTable.MLIDCFG_FrameID) {
//
// TR - 802.2
//
case TOKEN_RING_802_2_FRAME_ID:
//
// Set DSAP, SSAP and Control
//
if (ProtocolID[0] < 2) {
*CurrentPlace = ProtocolID[5];
CurrentPlace++;
*CurrentPlace = ProtocolID[5];
CurrentPlace++;
*CurrentPlace = 0x03;
CurrentPlace++;
} else if (ProtocolID[0] == 2) {
//
// Type I header
//
*CurrentPlace = ProtocolID[3];
CurrentPlace++;
*CurrentPlace = ProtocolID[4];
CurrentPlace++;
*CurrentPlace = ProtocolID[5];
CurrentPlace++;
} else {
//
// Type II header
//
*CurrentPlace = ProtocolID[2];
CurrentPlace++;
*CurrentPlace = ProtocolID[3];
CurrentPlace++;
*CurrentPlace = ProtocolID[4];
CurrentPlace++;
*CurrentPlace = ProtocolID[5];
CurrentPlace++;
}
break;
//
// TR - SNAP
//
case TOKEN_RING_SNAP_FRAME_ID:
//
// Set DSAP, SSAP and Control
//
*CurrentPlace = 0xAA;
CurrentPlace++;
*CurrentPlace = 0xAA;
CurrentPlace++;
*CurrentPlace = 0x03;
CurrentPlace++;
//
// Copy in ProtocolID
//
RtlCopyMemory(CurrentPlace, &(ProtocolID[1]), 5);
CurrentPlace += 5;
break;
default:
//
// Should never happen
//
ASSERT(0);
break;
}
break;
case NdisMedium802_3:
//
// Set DestinationAddress
//
RtlCopyMemory(CurrentPlace, DestinationAddress, 6);
CurrentPlace += 6;
//
// Set SourceAddress
//
RtlCopyMemory(CurrentPlace, Mlid->ConfigTable.MLIDCFG_NodeAddress, 6);
CurrentPlace += 6;
FrameLength += 12;
//
// Switch on frame type
//
switch (Mlid->ConfigTable.MLIDCFG_FrameID) {
//
// Ethernet 802.2
//
case ETHERNET_802_2_FRAME_ID:
FrameLength += 5;
//
// Set FrameLength
//
*CurrentPlace = (UINT8)((FrameLength >> 8) & 0xFF);
CurrentPlace++;
*CurrentPlace = (UINT8)(FrameLength & 0xFF);
CurrentPlace++;
//
// Set DSAP, SSAP and Control
//
if (ProtocolID[0] < 2) {
*CurrentPlace = ProtocolID[5];
CurrentPlace++;
*CurrentPlace = ProtocolID[5];
CurrentPlace++;
*CurrentPlace = 0x03;
CurrentPlace++;
} else if (ProtocolID[0] == 2) {
//
// Type I header
//
*CurrentPlace = ProtocolID[3];
CurrentPlace++;
*CurrentPlace = ProtocolID[4];
CurrentPlace++;
*CurrentPlace = ProtocolID[5];
CurrentPlace++;
} else {
//
// Type II header
//
*CurrentPlace = ProtocolID[2];
CurrentPlace++;
*CurrentPlace = ProtocolID[3];
CurrentPlace++;
*CurrentPlace = ProtocolID[4];
CurrentPlace++;
*CurrentPlace = ProtocolID[5];
CurrentPlace++;
}
break;
//
// Ethernet SNAP
//
case ETHERNET_SNAP_FRAME_ID:
FrameLength += 10;
//
// Set FrameLength
//
*CurrentPlace = (UINT8)((FrameLength >> 8) & 0xFF);
CurrentPlace++;
*CurrentPlace = (UINT8)(FrameLength & 0xFF);
CurrentPlace++;
//
// Set DSAP, SSAP and Control
//
*CurrentPlace = 0xAA;
CurrentPlace++;
*CurrentPlace = 0xAA;
CurrentPlace++;
*CurrentPlace = 0x03;
CurrentPlace++;
//
// Copy in ProtocolID
//
RtlCopyMemory(CurrentPlace, &(ProtocolID[1]), 5);
CurrentPlace += 5;
break;
//
// Ethernet Raw 802.3
//
case ETHERNET_802_3_FRAME_ID:
FrameLength += 2;
//
// Set FrameLength
//
*CurrentPlace = (UINT8)((FrameLength >> 8) & 0xFF);
CurrentPlace++;
*CurrentPlace = (UINT8)(FrameLength & 0xFF);
CurrentPlace++;
break;
//
// Ethernet II
//
case ETHERNET_II_FRAME_ID:
FrameLength += 2;
//
// Set FrameType
//*\\ Is this right? - Ethernet II, where is FrameType stored in ProtocolID?
*CurrentPlace = (UINT8)ProtocolID[4];
CurrentPlace++;
*CurrentPlace = (UINT8)ProtocolID[5];
CurrentPlace++;
break;
default:
//
// Should never happen
//
ASSERT(0);
break;
}
break;
case NdisMediumFddi:
//
// Set FCByte
//
*CurrentPlace = 0x57;
CurrentPlace ++;
//
// Set DestinationAddress
//
RtlCopyMemory(CurrentPlace, DestinationAddress, 6);
CurrentPlace += 6;
//
// Set SourceAddress
//
RtlCopyMemory(CurrentPlace, Mlid->ConfigTable.MLIDCFG_NodeAddress, 6);
CurrentPlace += 6;
FrameLength += 13;
//
// Switch on frame type
//
switch (Mlid->ConfigTable.MLIDCFG_FrameID) {
//
// FDDI 802.2
//
case FDDI_802_2_FRAME_ID:
if (ProtocolID[0] > 2) {
//
// Type II header
//
FrameLength += 6;
} else {
//
// Type I header
//
FrameLength += 5;
}
//
// Set FrameLength
//
*CurrentPlace = (UINT8)((FrameLength >> 8) & 0xFF);
CurrentPlace++;
*CurrentPlace = (UINT8)(FrameLength & 0xFF);
CurrentPlace++;
//
// Set DSAP, SSAP and Control
//
if (ProtocolID[0] < 2) {
*CurrentPlace = ProtocolID[5];
CurrentPlace++;
*CurrentPlace = ProtocolID[5];
CurrentPlace++;
*CurrentPlace = 0x03;
CurrentPlace++;
} else if (ProtocolID[0] == 2) {
//
// Type I header
//
*CurrentPlace = ProtocolID[3];
CurrentPlace++;
*CurrentPlace = ProtocolID[4];
CurrentPlace++;
*CurrentPlace = ProtocolID[5];
CurrentPlace++;
} else {
//
// Type II header
//
*CurrentPlace = ProtocolID[2];
CurrentPlace++;
*CurrentPlace = ProtocolID[3];
CurrentPlace++;
*CurrentPlace = ProtocolID[4];
CurrentPlace++;
*CurrentPlace = ProtocolID[5];
CurrentPlace++;
}
break;
//
// Fddi SNAP
//
case FDDI_SNAP_FRAME_ID:
FrameLength += 10;
//
// Set FrameLength
//
*CurrentPlace = (UINT8)((FrameLength >> 8) & 0xFF);
CurrentPlace++;
*CurrentPlace = (UINT8)(FrameLength & 0xFF);
CurrentPlace++;
//
// Set DSAP, SSAP and Control
//
*CurrentPlace = 0xAA;
CurrentPlace++;
*CurrentPlace = 0xAA;
CurrentPlace++;
*CurrentPlace = 0x03;
CurrentPlace++;
//
// Copy in ProtocolID
//
RtlCopyMemory(CurrentPlace, &(ProtocolID[1]), 5);
CurrentPlace += 5;
break;
default:
//
// Should never happen
//
ASSERT(0);
break;
}
break;
default:
//
// Should never happen
//
ASSERT(0);
break;
}
Reserved->MediaHeaderLength = FrameLength - DataLength;
}