📄 lan.c
字号:
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: datalink/lan.c
* PURPOSE: Local Area Network media routines
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/08-2000 Created
* arty -- Separate service 09/2004
*/
#include "precomp.h"
ULONG DebugTraceLevel = 0x7ffffff;
PDEVICE_OBJECT LanDeviceObject = NULL;
NDIS_STATUS NDISCall(
PLAN_ADAPTER Adapter,
NDIS_REQUEST_TYPE Type,
NDIS_OID OID,
PVOID Buffer,
UINT Length)
/*
* FUNCTION: Send a request to NDIS
* ARGUMENTS:
* Adapter = Pointer to a LAN_ADAPTER structure
* Type = Type of request (Set or Query)
* OID = Value to be set/queried for
* Buffer = Pointer to a buffer to use
* Length = Number of bytes in Buffer
* RETURNS:
* Status of operation
*/
{
NDIS_REQUEST Request;
NDIS_STATUS NdisStatus;
Request.RequestType = Type;
if (Type == NdisRequestSetInformation) {
Request.DATA.SET_INFORMATION.Oid = OID;
Request.DATA.SET_INFORMATION.InformationBuffer = Buffer;
Request.DATA.SET_INFORMATION.InformationBufferLength = Length;
} else {
Request.DATA.QUERY_INFORMATION.Oid = OID;
Request.DATA.QUERY_INFORMATION.InformationBuffer = Buffer;
Request.DATA.QUERY_INFORMATION.InformationBufferLength = Length;
}
if (Adapter->State != LAN_STATE_RESETTING) {
NdisRequest(&NdisStatus, Adapter->NdisHandle, &Request);
} else {
NdisStatus = NDIS_STATUS_NOT_ACCEPTED;
}
/* Wait for NDIS to complete the request */
if (NdisStatus == NDIS_STATUS_PENDING) {
KeWaitForSingleObject(&Adapter->Event,
UserRequest,
KernelMode,
FALSE,
NULL);
NdisStatus = Adapter->NdisStatus;
}
return NdisStatus;
}
VOID FreeAdapter(
PLAN_ADAPTER Adapter)
/*
* FUNCTION: Frees memory for a LAN_ADAPTER structure
* ARGUMENTS:
* Adapter = Pointer to LAN_ADAPTER structure to free
*/
{
exFreePool(Adapter);
}
VOID STDCALL ProtocolOpenAdapterComplete(
NDIS_HANDLE BindingContext,
NDIS_STATUS Status,
NDIS_STATUS OpenErrorStatus)
/*
* FUNCTION: Called by NDIS to complete opening of an adapter
* ARGUMENTS:
* BindingContext = Pointer to a device context (LAN_ADAPTER)
* Status = Status of the operation
* OpenErrorStatus = Additional status information
*/
{
PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
KeSetEvent(&Adapter->Event, 0, FALSE);
}
VOID STDCALL ProtocolCloseAdapterComplete(
NDIS_HANDLE BindingContext,
NDIS_STATUS Status)
/*
* FUNCTION: Called by NDIS to complete closing an adapter
* ARGUMENTS:
* BindingContext = Pointer to a device context (LAN_ADAPTER)
* Status = Status of the operation
*/
{
PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
Adapter->NdisStatus = Status;
KeSetEvent(&Adapter->Event, 0, FALSE);
}
VOID STDCALL ProtocolResetComplete(
NDIS_HANDLE BindingContext,
NDIS_STATUS Status)
/*
* FUNCTION: Called by NDIS to complete resetting an adapter
* ARGUMENTS:
* BindingContext = Pointer to a device context (LAN_ADAPTER)
* Status = Status of the operation
*/
{
LA_DbgPrint(MID_TRACE, ("Called.\n"));
}
VOID STDCALL ProtocolRequestComplete(
NDIS_HANDLE BindingContext,
PNDIS_REQUEST NdisRequest,
NDIS_STATUS Status)
/*
* FUNCTION: Called by NDIS to complete a request
* ARGUMENTS:
* BindingContext = Pointer to a device context (LAN_ADAPTER)
* NdisRequest = Pointer to an object describing the request
* Status = Status of the operation
*/
{
PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
/* Save status of request and signal an event */
Adapter->NdisStatus = Status;
KeSetEvent(&Adapter->Event, 0, FALSE);
}
VOID STDCALL ProtocolSendComplete(
NDIS_HANDLE BindingContext,
PNDIS_PACKET Packet,
NDIS_STATUS Status)
/*
* FUNCTION: Called by NDIS to complete sending process
* ARGUMENTS:
* BindingContext = Pointer to a device context (LAN_ADAPTER)
* Packet = Pointer to a packet descriptor
* Status = Status of the operation
*/
{
/*PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;*/
LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
/*(*PC(Packet)->DLComplete)(Adapter->Context, Packet, Status);*/
LA_DbgPrint(DEBUG_DATALINK, ("Finished\n"));
}
VOID STDCALL ProtocolTransferDataComplete(
NDIS_HANDLE BindingContext,
PNDIS_PACKET Packet,
NDIS_STATUS Status,
UINT BytesTransferred)
/*
* FUNCTION: Called by NDIS to complete reception of data
* ARGUMENTS:
* BindingContext = Pointer to a device context (LAN_ADAPTER)
* Packet = Pointer to a packet descriptor
* Status = Status of the operation
* BytesTransferred = Number of bytes transferred
* NOTES:
* If the packet was successfully received, determine the protocol
* type and pass it to the correct receive handler
*/
{
PLIST_ENTRY ListEntry, ReadListEntry;
PLAN_PROTOCOL Proto;
PLAN_PACKET_HEADER Header;
PLAN_DEVICE_EXT DeviceExt = LanDeviceObject->DeviceExtension;
UINT i;
UINT PacketType;
UINT ContigSize;
PIRP ReadIrp;
KIRQL OldIrql;
LAN_PACKET LPPacket;
PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
KeAcquireSpinLock( &DeviceExt->Lock, &OldIrql );
if (Status == NDIS_STATUS_SUCCESS) {
PNDIS_BUFFER NdisBuffer;
NdisGetFirstBufferFromPacket(Packet,
&NdisBuffer,
&LPPacket.EthHeader,
&ContigSize,
&LPPacket.TotalSize);
LPPacket.TotalSize = BytesTransferred;
/* Determine which upper layer protocol that should receive
this packet and pass it to the correct receive handler */
/*OskitDumpBuffer( IPPacket.Header, BytesTransferred );*/
PacketType = LPPacket.EthHeader->EType;
LA_DbgPrint
(DEBUG_DATALINK,
("Ether Type = %x Total = %d Packet %x Payload %x\n",
PacketType, LPPacket.TotalSize, LPPacket.EthHeader,
LPPacket.EthHeader + 1));
NdisBuffer->Next = NULL;
for( ListEntry = DeviceExt->ProtocolListHead.Flink;
ListEntry != &DeviceExt->ProtocolListHead;
ListEntry = ListEntry->Flink ) {
Proto = CONTAINING_RECORD(ListEntry, LAN_PROTOCOL, ListEntry);
LA_DbgPrint(MID_TRACE,("Examining protocol %x\n", Proto));
for( i = 0; i < Proto->NumEtherTypes; i++ ) {
LA_DbgPrint(MID_TRACE,(".Accepts proto %x\n",
Proto->EtherType[i]));
if( Proto->EtherType[i] == PacketType &&
!IsListEmpty( &Proto->ReadIrpListHead ) ) {
ReadListEntry = RemoveHeadList( &Proto->ReadIrpListHead );
ReadIrp = CONTAINING_RECORD(ReadListEntry, IRP,
Tail.Overlay.ListEntry );
LA_DbgPrint(MID_TRACE,("..Irp %x\n", ReadIrp));
_SEH_TRY {
Header = ReadIrp->AssociatedIrp.SystemBuffer;
LA_DbgPrint
(MID_TRACE,
("Writing packet at %x\n", Header));
Header->Fixed.Adapter = Adapter->Index;
Header->Fixed.AddressType = Adapter->Media;
Header->Fixed.AddressLen = IEEE_802_ADDR_LENGTH;
Header->Fixed.PacketType = PacketType;
RtlCopyMemory( Header->Address,
LPPacket.EthHeader->SrcAddr,
IEEE_802_ADDR_LENGTH );
if( Proto->Buffered ) {
LA_DbgPrint(MID_TRACE,("Buffered copy\n"));
RtlCopyMemory
( Header->Address +
IEEE_802_ADDR_LENGTH,
LPPacket.EthHeader + 1,
LPPacket.TotalSize -
sizeof(*LPPacket.EthHeader) );
Header->Fixed.Mdl = NULL;
} else
Header->Fixed.Mdl = NdisBuffer;
ReadIrp->IoStatus.Status = 0;
ReadIrp->IoStatus.Information =
(Header->Address + IEEE_802_ADDR_LENGTH +
LPPacket.TotalSize -
sizeof(*LPPacket.EthHeader)) -
(PCHAR)Header;
LA_DbgPrint(MID_TRACE,("Bytes returned %d\n",
ReadIrp->IoStatus.Information));
IoCompleteRequest( ReadIrp, IO_NETWORK_INCREMENT );
} _SEH_HANDLE {
LA_DbgPrint
(MIN_TRACE,
("Failed write to packet in client\n"));
ReadIrp->IoStatus.Status = STATUS_ACCESS_VIOLATION;
ReadIrp->IoStatus.Information = 0;
IoCompleteRequest( ReadIrp, IO_NETWORK_INCREMENT );
} _SEH_END;
break;
}
}
}
}
KeReleaseSpinLock( &DeviceExt->Lock, OldIrql );
FreeNdisPacket( Packet );
}
NDIS_STATUS STDCALL ProtocolReceive(
NDIS_HANDLE BindingContext,
NDIS_HANDLE MacReceiveContext,
PVOID HeaderBuffer,
UINT HeaderBufferSize,
PVOID LookaheadBuffer,
UINT LookaheadBufferSize,
UINT PacketSize)
/*
* FUNCTION: Called by NDIS when a packet has been received on the physical link
* ARGUMENTS:
* BindingContext = Pointer to a device context (LAN_ADAPTER)
* MacReceiveContext = Handle used by underlying NIC driver
* HeaderBuffer = Pointer to a buffer containing the packet header
* HeaderBufferSize = Number of bytes in HeaderBuffer
* LookaheadBuffer = Pointer to a buffer containing buffered packet data
* LookaheadBufferSize = Size of LookaheadBuffer. May be less than asked for
* PacketSize = Overall size of the packet (not including header)
* RETURNS:
* Status of operation
*/
{
USHORT EType;
UINT PacketType, BytesTransferred;
PCHAR BufferData;
NDIS_STATUS NdisStatus;
PNDIS_PACKET NdisPacket;
PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
LA_DbgPrint(DEBUG_DATALINK, ("Called. (packetsize %d)\n",PacketSize));
if (Adapter->State != LAN_STATE_STARTED) {
LA_DbgPrint(DEBUG_DATALINK, ("Adapter is stopped.\n"));
return NDIS_STATUS_NOT_ACCEPTED;
}
if (HeaderBufferSize < Adapter->HeaderSize) {
LA_DbgPrint(DEBUG_DATALINK, ("Runt frame received.\n"));
return NDIS_STATUS_NOT_ACCEPTED;
}
PacketType = EType;
/* Get a transfer data packet */
KeAcquireSpinLockAtDpcLevel(&Adapter->Lock);
NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL, Adapter->MTU );
if( NdisStatus != NDIS_STATUS_SUCCESS ) return NDIS_STATUS_NOT_ACCEPTED;
LA_DbgPrint(DEBUG_DATALINK, ("pretransfer LookaheadBufferSize %d packsize %d\n",LookaheadBufferSize,PacketSize));
{
UINT temp;
temp = PacketSize;
GetDataPtr( NdisPacket, 0, &BufferData, &temp );
}
LA_DbgPrint(DEBUG_DATALINK, ("pretransfer LookaheadBufferSize %d HeaderBufferSize %d packsize %d\n",LookaheadBufferSize,HeaderBufferSize,PacketSize));
/* Get the data */
NdisTransferData(&NdisStatus,
Adapter->NdisHandle,
MacReceiveContext,
0,
PacketSize + HeaderBufferSize,
NdisPacket,
&BytesTransferred);
LA_DbgPrint(DEBUG_DATALINK, ("Calling complete\n"));
if (NdisStatus != NDIS_STATUS_PENDING)
ProtocolTransferDataComplete(BindingContext,
NdisPacket,
NdisStatus,
PacketSize + HeaderBufferSize);
/* Release the packet descriptor */
KeReleaseSpinLockFromDpcLevel(&Adapter->Lock);
LA_DbgPrint(DEBUG_DATALINK, ("leaving\n"));
return NDIS_STATUS_SUCCESS;
}
VOID STDCALL ProtocolReceiveComplete(
NDIS_HANDLE BindingContext)
/*
* FUNCTION: Called by NDIS when we're done receiving data
* ARGUMENTS:
* BindingContext = Pointer to a device context (LAN_ADAPTER)
*/
{
LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
}
VOID STDCALL ProtocolStatus(
NDIS_HANDLE BindingContext,
NDIS_STATUS GenerelStatus,
PVOID StatusBuffer,
UINT StatusBufferSize)
/*
* FUNCTION: Called by NDIS when the underlying driver has changed state
* ARGUMENTS:
* BindingContext = Pointer to a device context (LAN_ADAPTER)
* GenerelStatus = A generel status code
* StatusBuffer = Pointer to a buffer with medium-specific data
* StatusBufferSize = Number of bytes in StatusBuffer
*/
{
LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
}
VOID STDCALL ProtocolStatusComplete(
NDIS_HANDLE NdisBindingContext)
/*
* FUNCTION: Called by NDIS when a status-change has occurred
* ARGUMENTS:
* BindingContext = Pointer to a device context (LAN_ADAPTER)
*/
{
LA_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
}
VOID STDCALL ProtocolBindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE BindContext,
IN PNDIS_STRING DeviceName,
IN PVOID SystemSpecific1,
IN PVOID SystemSpecific2)
/*
* FUNCTION: Called by NDIS during NdisRegisterProtocol to set up initial
* bindings, and periodically thereafer as new adapters come online
* ARGUMENTS:
* Status: Return value to NDIS
* BindContext: Handle provided by NDIS to track pending binding operations
* DeviceName: Name of the miniport device to bind to
* SystemSpecific1: Pointer to a registry path with protocol-specific configuration information
* SystemSpecific2: Unused & must not be touched
*/
{
/* XXX confirm that this is still true, or re-word the following comment */
/* we get to ignore BindContext because we will never pend an operation with NDIS */
LA_DbgPrint(DEBUG_DATALINK, ("Called with registry path %wZ\n", SystemSpecific1));
*Status = LANRegisterAdapter(DeviceName, SystemSpecific1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -