* REVISIONS:
* CSH 01/08-2000 Created
*/
-#include <tcpip.h>
-#include <lan.h>
-#include <address.h>
-#include <routines.h>
-#include <transmit.h>
-#include <receive.h>
-#include <arp.h>
+#include "precomp.h"
+
+/* Define this to bugcheck on double complete */
+/* #define BREAK_ON_DOUBLE_COMPLETE */
+
+UINT TransferDataCalled = 0;
+UINT TransferDataCompleteCalled = 0;
+UINT LanReceiveWorkerCalled = 0;
+BOOLEAN LanReceiveWorkerBusy = FALSE;
+
+#define CCS_ROOT L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet"
+#define TCPIP_GUID L"{4D36E972-E325-11CE-BFC1-08002BE10318}"
+
+#define NGFP(_Packet) \
+ { \
+ PVOID _Header; \
+ ULONG _ContigSize, _TotalSize; \
+ PNDIS_BUFFER _NdisBuffer; \
+ \
+ TI_DbgPrint(MID_TRACE,("Checking Packet %x\n", _Packet)); \
+ NdisGetFirstBufferFromPacket(_Packet, \
+ &_NdisBuffer, \
+ &_Header, \
+ &_ContigSize, \
+ &_TotalSize); \
+ TI_DbgPrint(MID_TRACE,("NdisBuffer: %x\n", _NdisBuffer)); \
+ TI_DbgPrint(MID_TRACE,("Header : %x\n", _Header)); \
+ TI_DbgPrint(MID_TRACE,("ContigSize: %x\n", _ContigSize)); \
+ TI_DbgPrint(MID_TRACE,("TotalSize : %x\n", _TotalSize)); \
+ }
+
+typedef struct _LAN_WQ_ITEM {
+ LIST_ENTRY ListEntry;
+ PNDIS_PACKET Packet;
+ PLAN_ADAPTER Adapter;
+ UINT BytesTransferred;
+} LAN_WQ_ITEM, *PLAN_WQ_ITEM;
NDIS_HANDLE NdisProtocolHandle = (NDIS_HANDLE)NULL;
BOOLEAN ProtocolRegistered = FALSE;
LIST_ENTRY AdapterListHead;
KSPIN_LOCK AdapterListLock;
+/* Double complete protection */
+KSPIN_LOCK LanSendCompleteLock;
+LIST_ENTRY LanSendCompleteList;
+
+VOID LanChainCompletion( PLAN_ADAPTER Adapter, PNDIS_PACKET NdisPacket ) {
+ PLAN_WQ_ITEM PendingCompletion =
+ ExAllocatePool( NonPagedPool, sizeof(LAN_WQ_ITEM) );
+
+ if( !PendingCompletion ) return;
+
+ PendingCompletion->Packet = NdisPacket;
+ PendingCompletion->Adapter = Adapter;
+
+ ExInterlockedInsertTailList( &LanSendCompleteList,
+ &PendingCompletion->ListEntry,
+ &LanSendCompleteLock );
+}
+
+BOOLEAN LanShouldComplete( PLAN_ADAPTER Adapter, PNDIS_PACKET NdisPacket ) {
+ PLIST_ENTRY ListEntry;
+ PLAN_WQ_ITEM CompleteEntry;
+ KIRQL OldIrql;
+
+ KeAcquireSpinLock( &LanSendCompleteLock, &OldIrql );
+ for( ListEntry = LanSendCompleteList.Flink;
+ ListEntry != &LanSendCompleteList;
+ ListEntry = ListEntry->Flink ) {
+ CompleteEntry = CONTAINING_RECORD(ListEntry, LAN_WQ_ITEM, ListEntry);
+
+ if( CompleteEntry->Adapter == Adapter &&
+ CompleteEntry->Packet == NdisPacket ) {
+ RemoveEntryList( ListEntry );
+ KeReleaseSpinLock( &LanSendCompleteLock, OldIrql );
+ ExFreePool( CompleteEntry );
+ return TRUE;
+ }
+ }
+ KeReleaseSpinLock( &LanSendCompleteLock, OldIrql );
+
+ DbgPrint("NDIS completed the same send packet twice "
+ "(Adapter %x Packet %x)!!\n", Adapter, NdisPacket);
+#ifdef BREAK_ON_DOUBLE_COMPLETE
+ KeBugCheck(0);
+#endif
+
+ return FALSE;
+}
NDIS_STATUS NDISCall(
PLAN_ADAPTER Adapter,
}
-PNDIS_PACKET AllocateTDPacket(
+VOID FreeAdapter(
PLAN_ADAPTER Adapter)
/*
- * FUNCTION: Allocates an NDIS packet for NdisTransferData
+ * FUNCTION: Frees memory for a LAN_ADAPTER structure
* ARGUMENTS:
- * Adapter = Pointer to LAN_ADAPTER structure
- * RETURNS:
- * Pointer to NDIS packet or NULL if there was not enough free
- * non-paged memory
+ * Adapter = Pointer to LAN_ADAPTER structure to free
*/
{
- NDIS_STATUS NdisStatus;
- PNDIS_PACKET NdisPacket;
- PNDIS_BUFFER Buffer;
- PVOID Data;
-
- NdisAllocatePacket(&NdisStatus, &NdisPacket, GlobalPacketPool);
- if (NdisStatus != NDIS_STATUS_SUCCESS)
- return NULL;
-
- Data = ExAllocatePool(NonPagedPool, Adapter->MTU);
- if (!Data) {
- NdisFreePacket(NdisPacket);
- return NULL;
- }
-
- NdisAllocateBuffer(&NdisStatus,
- &Buffer,
- GlobalBufferPool,
- Data,
- Adapter->MTU);
- if (NdisStatus != NDIS_STATUS_SUCCESS) {
- NdisFreePacket(NdisPacket);
- ExFreePool(Data);
- return NULL;
- }
-
- NdisChainBufferAtFront(NdisPacket, Buffer);
-
- PC(NdisPacket)->Context = NULL; /* End of list */
-
- return NdisPacket;
+ exFreePool(Adapter);
}
-VOID FreeTDPackets(
- PLAN_ADAPTER Adapter)
-/*
- * FUNCTION: Frees transfer data packets
- * ARGUMENTS:
- * Adapter = Pointer to LAN_ADAPTER structure
- */
-{
- PNDIS_PACKET NdisPacket, Next;
-
- /* Release transfer data packets */
- NdisPacket = Adapter->TDPackets;
- while (NdisPacket) {
- Next = PC(NdisPacket)->Context;
- FreeNdisPacket(NdisPacket);
- NdisPacket = Next;
- }
- Adapter->TDPackets = NULL;
-}
-
+NTSTATUS TcpipLanGetDwordOid
+( PIP_INTERFACE Interface,
+ NDIS_OID Oid,
+ PDWORD Result ) {
+ /* Get maximum frame size */
+ if( Interface->Context ) {
+ return NDISCall((PLAN_ADAPTER)Interface->Context,
+ NdisRequestQueryInformation,
+ Oid,
+ Result,
+ sizeof(DWORD));
+ } else switch( Oid ) { /* Loopback Case */
+ case OID_GEN_HARDWARE_STATUS:
+ *Result = NdisHardwareStatusReady;
+ return STATUS_SUCCESS;
-VOID FreeAdapter(
- PLAN_ADAPTER Adapter)
-/*
- * FUNCTION: Frees memory for a LAN_ADAPTER structure
- * ARGUMENTS:
- * Adapter = Pointer to LAN_ADAPTER structure to free
- */
-{
- FreeTDPackets(Adapter);
- ExFreePool(Adapter);
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
}
-VOID ProtocolOpenAdapterComplete(
+VOID STDCALL ProtocolOpenAdapterComplete(
NDIS_HANDLE BindingContext,
NDIS_STATUS Status,
NDIS_STATUS OpenErrorStatus)
}
-VOID ProtocolCloseAdapterComplete(
+VOID STDCALL ProtocolCloseAdapterComplete(
NDIS_HANDLE BindingContext,
NDIS_STATUS Status)
/*
}
-VOID ProtocolResetComplete(
+VOID STDCALL ProtocolResetComplete(
NDIS_HANDLE BindingContext,
NDIS_STATUS Status)
/*
}
-VOID ProtocolRequestComplete(
+VOID STDCALL ProtocolRequestComplete(
NDIS_HANDLE BindingContext,
PNDIS_REQUEST NdisRequest,
NDIS_STATUS Status)
}
-VOID ProtocolSendComplete(
+VOID STDCALL ProtocolSendComplete(
NDIS_HANDLE BindingContext,
PNDIS_PACKET Packet,
NDIS_STATUS Status)
* Status = Status of the operation
*/
{
- PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
+ TI_DbgPrint(DEBUG_DATALINK, ("Calling completion routine\n"));
+ if( LanShouldComplete( (PLAN_ADAPTER)BindingContext, Packet ) ) {
+ ASSERT_KM_POINTER(Packet);
+ ASSERT_KM_POINTER(PC(Packet));
+ ASSERT_KM_POINTER(PC(Packet)->DLComplete);
+ (*PC(Packet)->DLComplete)( PC(Packet)->Context, Packet, Status);
+ TI_DbgPrint(DEBUG_DATALINK, ("Finished\n"));
+ }
+}
- TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
+VOID LanReceiveWorker( PVOID Context ) {
+ UINT PacketType;
+ PLAN_WQ_ITEM WorkItem = (PLAN_WQ_ITEM)Context;
+ PNDIS_PACKET Packet;
+ PLAN_ADAPTER Adapter;
+ UINT BytesTransferred;
+ PNDIS_BUFFER NdisBuffer;
+ IP_PACKET IPPacket;
- AdjustPacket(Packet, Adapter->HeaderSize, PC(Packet)->DLOffset);
+ TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
- (*PC(Packet)->DLComplete)(Adapter->Context, Packet, Status);
+ Packet = WorkItem->Packet;
+ Adapter = WorkItem->Adapter;
+ BytesTransferred = WorkItem->BytesTransferred;
+
+ IPPacket.NdisPacket = Packet;
+
+ NdisGetFirstBufferFromPacket(Packet,
+ &NdisBuffer,
+ &IPPacket.Header,
+ &IPPacket.ContigSize,
+ &IPPacket.TotalSize);
+
+ IPPacket.ContigSize = IPPacket.TotalSize = BytesTransferred;
+ /* Determine which upper layer protocol that should receive
+ this packet and pass it to the correct receive handler */
+
+ TI_DbgPrint(MID_TRACE,
+ ("ContigSize: %d, TotalSize: %d, BytesTransferred: %d\n",
+ IPPacket.ContigSize, IPPacket.TotalSize,
+ BytesTransferred));
+
+ PacketType = PC(IPPacket.NdisPacket)->PacketType;
+ IPPacket.Position = 0;
+
+ TI_DbgPrint
+ (DEBUG_DATALINK,
+ ("Ether Type = %x ContigSize = %d Total = %d\n",
+ PacketType, IPPacket.ContigSize, IPPacket.TotalSize));
+
+ switch (PacketType) {
+ case ETYPE_IPv4:
+ case ETYPE_IPv6:
+ TI_DbgPrint(MID_TRACE,("Received IP Packet\n"));
+ IPReceive(Adapter->Context, &IPPacket);
+ break;
+ case ETYPE_ARP:
+ TI_DbgPrint(MID_TRACE,("Received ARP Packet\n"));
+ ARPReceive(Adapter->Context, &IPPacket);
+ default:
+ break;
+ }
+
+ FreeNdisPacket( Packet );
}
+VOID LanSubmitReceiveWork(
+ NDIS_HANDLE BindingContext,
+ PNDIS_PACKET Packet,
+ NDIS_STATUS Status,
+ UINT BytesTransferred) {
+ LAN_WQ_ITEM WQItem;
+ PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
+ PVOID LanWorkItem;
+
+ TI_DbgPrint(DEBUG_DATALINK,("called\n"));
+
+ WQItem.Packet = Packet;
+ WQItem.Adapter = Adapter;
+ WQItem.BytesTransferred = BytesTransferred;
+
+ if( !ChewCreate
+ ( &LanWorkItem, sizeof(LAN_WQ_ITEM), LanReceiveWorker, &WQItem ) )
+ ASSERT(0);
+}
-VOID ProtocolTransferDataComplete(
+VOID STDCALL ProtocolTransferDataComplete(
NDIS_HANDLE BindingContext,
PNDIS_PACKET Packet,
NDIS_STATUS Status,
* type and pass it to the correct receive handler
*/
{
- UINT PacketType;
- PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
- TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
-
- if (Status == NDIS_STATUS_SUCCESS) {
- PNDIS_BUFFER NdisBuffer;
- IP_PACKET IPPacket;
-
- IPPacket.NdisPacket = Packet;
-
- NdisGetFirstBufferFromPacket(Packet,
- &NdisBuffer,
- &IPPacket.Header,
- &IPPacket.ContigSize,
- &IPPacket.TotalSize);
-
- /* Determine which upper layer protocol that should receive
- this packet and pass it to the correct receive handler */
- PacketType = ((PETH_HEADER)IPPacket.Header)->EType;
- switch (PacketType) {
- case ETYPE_IPv4:
- case ETYPE_IPv6:
- IPReceive(Adapter->Context, &IPPacket);
- break;
- case ETYPE_ARP:
- ARPReceive(Adapter->Context, &IPPacket);
- default:
- break;
- }
- }
+ TI_DbgPrint(DEBUG_DATALINK,("called\n"));
- /* Release the packet descriptor */
- KeAcquireSpinLockAtDpcLevel(&Adapter->Lock);
+ TransferDataCompleteCalled++;
+ ASSERT(TransferDataCompleteCalled <= TransferDataCalled);
- PC(Packet)->Context = Adapter->TDPackets;
- Adapter->TDPackets = Packet;
+ if( Status != NDIS_STATUS_SUCCESS ) return;
- KeReleaseSpinLockFromDpcLevel(&Adapter->Lock);
+ LanSubmitReceiveWork( BindingContext, Packet, Status, BytesTransferred );
}
-
-NDIS_STATUS ProtocolReceive(
+NDIS_STATUS STDCALL ProtocolReceive(
NDIS_HANDLE BindingContext,
NDIS_HANDLE MacReceiveContext,
PVOID HeaderBuffer,
*/
{
USHORT EType;
- UINT PacketType;
+ UINT PacketType, BytesTransferred;
+ UINT temp;
IP_PACKET IPPacket;
+ PCHAR BufferData;
+ NDIS_STATUS NdisStatus;
PNDIS_PACKET NdisPacket;
- PNDIS_BUFFER NdisBuffer;
PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
PETH_HEADER EHeader = (PETH_HEADER)HeaderBuffer;
- TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
+ TI_DbgPrint(DEBUG_DATALINK, ("Called. (packetsize %d)\n",PacketSize));
if (Adapter->State != LAN_STATE_STARTED) {
TI_DbgPrint(DEBUG_DATALINK, ("Adapter is stopped.\n"));
/* Get a transfer data packet */
- KeAcquireSpinLockAtDpcLevel(&Adapter->Lock);
+ TI_DbgPrint(DEBUG_DATALINK, ("Adapter: %x (MTU %d)\n",
+ Adapter, Adapter->MTU));
- NdisPacket = Adapter->TDPackets;
- if (NdisPacket == (PNDIS_PACKET)NULL) {
- TI_DbgPrint(DEBUG_DATALINK, ("No available packet descriptors.\n"));
- /* We don't have a free packet descriptor. Drop the packet */
- KeReleaseSpinLockFromDpcLevel(&Adapter->Lock);
- return NDIS_STATUS_SUCCESS;
+ NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL,
+ PacketSize + HeaderBufferSize );
+ if( NdisStatus != NDIS_STATUS_SUCCESS ) {
+ return NDIS_STATUS_NOT_ACCEPTED;
}
- Adapter->TDPackets = PC(NdisPacket)->Context;
- KeReleaseSpinLockFromDpcLevel(&Adapter->Lock);
+ PC(NdisPacket)->PacketType = PacketType;
- if (LookaheadBufferSize < PacketSize) {
- NDIS_STATUS NdisStatus;
- UINT BytesTransferred;
-
- /* Get the data */
- NdisTransferData(&NdisStatus,
- Adapter->NdisHandle,
- MacReceiveContext,
- 0,
- PacketSize,
- NdisPacket,
- &BytesTransferred);
- if (NdisStatus != NDIS_STATUS_PENDING)
- ProtocolTransferDataComplete(BindingContext,
- NdisPacket,
- NdisStatus,
- BytesTransferred);
+ TI_DbgPrint(DEBUG_DATALINK, ("pretransfer LookaheadBufferSize %d packsize %d\n",LookaheadBufferSize,PacketSize));
- return NDIS_STATUS_SUCCESS;
- }
-
- /* We got all the data in the lookahead buffer */
+ GetDataPtr( NdisPacket, 0, &BufferData, &temp );
IPPacket.NdisPacket = NdisPacket;
-
- NdisGetFirstBufferFromPacket(NdisPacket,
- &NdisBuffer,
- &IPPacket.Header,
- &IPPacket.ContigSize,
- &IPPacket.TotalSize);
-
- RtlCopyMemory(IPPacket.Header, LookaheadBuffer, PacketSize);
-
- switch (PacketType) {
- case ETYPE_IPv4:
- case ETYPE_IPv6:
- IPReceive(Adapter->Context, &IPPacket);
- break;
- case ETYPE_ARP:
- ARPReceive(Adapter->Context, &IPPacket);
- break;
- default:
- break;
+ IPPacket.Position = 0;
+
+ TransferDataCalled++;
+
+ if (LookaheadBufferSize == PacketSize)
+ {
+ /* Optimized code path for packets that are fully contained in
+ * the lookahead buffer. */
+ NdisCopyLookaheadData(BufferData,
+ LookaheadBuffer,
+ LookaheadBufferSize,
+ Adapter->MacOptions);
}
+ else
+ {
+ if (NdisStatus == NDIS_STATUS_SUCCESS)
+ {
+ ASSERT(PacketSize <= Adapter->MTU);
+
+ NdisTransferData(&NdisStatus, Adapter->NdisHandle,
+ MacReceiveContext, 0, PacketSize,
+ NdisPacket, &BytesTransferred);
+ }
+ else
+ {
+ BytesTransferred = 0;
+ }
+ }
+ TI_DbgPrint(DEBUG_DATALINK, ("Calling complete\n"));
- /* Release the packet descriptor */
- KeAcquireSpinLockAtDpcLevel(&Adapter->Lock);
-
- PC(NdisPacket)->Context = Adapter->TDPackets;
- Adapter->TDPackets = NdisPacket;
+ if (NdisStatus != NDIS_STATUS_PENDING)
+ ProtocolTransferDataComplete(BindingContext,
+ NdisPacket,
+ NdisStatus,
+ PacketSize);
- KeReleaseSpinLockFromDpcLevel(&Adapter->Lock);
+ TI_DbgPrint(DEBUG_DATALINK, ("leaving\n"));
return NDIS_STATUS_SUCCESS;
}
-VOID ProtocolReceiveComplete(
+VOID STDCALL ProtocolReceiveComplete(
NDIS_HANDLE BindingContext)
/*
* FUNCTION: Called by NDIS when we're done receiving data
}
-VOID ProtocolStatus(
+VOID STDCALL ProtocolStatus(
NDIS_HANDLE BindingContext,
NDIS_STATUS GenerelStatus,
PVOID StatusBuffer,
}
-VOID ProtocolStatusComplete(
+VOID STDCALL ProtocolStatusComplete(
NDIS_HANDLE NdisBindingContext)
/*
* FUNCTION: Called by NDIS when a status-change has occurred
TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
}
-VOID ProtocolBindAdapter(
+VOID STDCALL ProtocolBindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE BindContext,
IN PNDIS_STRING DeviceName,
* 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 */
- TI_DbgPrint(DEBUG_DATALINK, ("Called with registry path %wZ\n", SystemSpecific1));
- *Status = LANRegisterAdapter(DeviceName, SystemSpecific1);
+ /* 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 */
+ TI_DbgPrint(DEBUG_DATALINK, ("Called with registry path %wZ for %wZ\n", SystemSpecific1, DeviceName));
+ *Status = LANRegisterAdapter(DeviceName, SystemSpecific1);
}
{
NDIS_STATUS NdisStatus;
PETH_HEADER EHeader;
- PVOID Data;
+ PCHAR Data;
+ UINT Size;
+ KIRQL OldIrql;
PLAN_ADAPTER Adapter = (PLAN_ADAPTER)Context;
- TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
+ TI_DbgPrint(DEBUG_DATALINK,
+ ("Called( NdisPacket %x, Offset %d, Adapter %x )\n",
+ NdisPacket, Offset, Adapter));
+
+ TI_DbgPrint(DEBUG_DATALINK,
+ ("Adapter Address [%02x %02x %02x %02x %02x %02x]\n",
+ Adapter->HWAddress[0] & 0xff,
+ Adapter->HWAddress[1] & 0xff,
+ Adapter->HWAddress[2] & 0xff,
+ Adapter->HWAddress[3] & 0xff,
+ Adapter->HWAddress[4] & 0xff,
+ Adapter->HWAddress[5] & 0xff));
+
+ /* XXX arty -- Handled adjustment in a saner way than before ...
+ * not needed immediately */
+ GetDataPtr( NdisPacket, 0, &Data, &Size );
- /* NDIS send routines don't have an offset argument so we
- must offset the data in upper layers and adjust the
- packet here. We save the offset in the packet context
- area so it can be undone before we release the packet */
- Data = AdjustPacket(NdisPacket, Offset, Adapter->HeaderSize);
- PC(NdisPacket)->DLOffset = Offset;
+ LanChainCompletion( Adapter, NdisPacket );
if (Adapter->State == LAN_STATE_STARTED) {
switch (Adapter->Media) {
RtlCopyMemory(EHeader->SrcAddr, Adapter->HWAddress, IEEE_802_ADDR_LENGTH);
switch (Type) {
- case LAN_PROTO_IPv4:
- EHeader->EType = ETYPE_IPv4;
- break;
- case LAN_PROTO_ARP:
- EHeader->EType = ETYPE_ARP;
- break;
- case LAN_PROTO_IPv6:
- EHeader->EType = ETYPE_IPv6;
- break;
- default:
+ case LAN_PROTO_IPv4:
+ EHeader->EType = ETYPE_IPv4;
+ break;
+ case LAN_PROTO_ARP:
+ EHeader->EType = ETYPE_ARP;
+ break;
+ case LAN_PROTO_IPv6:
+ EHeader->EType = ETYPE_IPv6;
+ break;
+ default:
#ifdef DBG
- /* Should not happen */
- TI_DbgPrint(MIN_TRACE, ("Unknown LAN protocol.\n"));
+ /* Should not happen */
+ TI_DbgPrint(MIN_TRACE, ("Unknown LAN protocol.\n"));
- ProtocolSendComplete((NDIS_HANDLE)Context,
- NdisPacket,
- NDIS_STATUS_FAILURE);
+ ProtocolSendComplete((NDIS_HANDLE)Context,
+ NdisPacket,
+ NDIS_STATUS_FAILURE);
#endif
- return;
+ return;
}
break;
break;
}
+ TI_DbgPrint( MID_TRACE, ("LinkAddress: %x\n", LinkAddress));
+ if( LinkAddress ) {
+ TI_DbgPrint
+ ( MID_TRACE,
+ ("Link Address [%02x %02x %02x %02x %02x %02x]\n",
+ ((PCHAR)LinkAddress)[0] & 0xff,
+ ((PCHAR)LinkAddress)[1] & 0xff,
+ ((PCHAR)LinkAddress)[2] & 0xff,
+ ((PCHAR)LinkAddress)[3] & 0xff,
+ ((PCHAR)LinkAddress)[4] & 0xff,
+ ((PCHAR)LinkAddress)[5] & 0xff));
+ }
+
+ TcpipAcquireSpinLock( &Adapter->Lock, &OldIrql );
+ TI_DbgPrint(MID_TRACE, ("NdisSend\n"));
NdisSend(&NdisStatus, Adapter->NdisHandle, NdisPacket);
+ TI_DbgPrint(MID_TRACE, ("NdisSend %s\n",
+ NdisStatus == NDIS_STATUS_PENDING ?
+ "Pending" : "Complete"));
+ TcpipReleaseSpinLock( &Adapter->Lock, OldIrql );
+
+ /* I had a talk with vizzini: these really ought to be here.
+ * we're supposed to see these completed by ndis *only* when
+ * status_pending is returned. Note that this is different from
+ * the situation with IRPs. */
if (NdisStatus != NDIS_STATUS_PENDING)
ProtocolSendComplete((NDIS_HANDLE)Context, NdisPacket, NdisStatus);
} else {
}
}
+static NTSTATUS
+OpenRegistryKey( PNDIS_STRING RegistryPath, PHANDLE RegHandle ) {
+ OBJECT_ATTRIBUTES Attributes;
+ NTSTATUS Status;
+
+ InitializeObjectAttributes(&Attributes, RegistryPath, OBJ_CASE_INSENSITIVE, 0, 0);
+ Status = ZwOpenKey(RegHandle, KEY_ALL_ACCESS, &Attributes);
+ return Status;
+}
+
+static NTSTATUS ReadStringFromRegistry( HANDLE RegHandle,
+ PWCHAR RegistryValue,
+ PUNICODE_STRING String ) {
+ UNICODE_STRING ValueName;
+ UNICODE_STRING UnicodeString;
+ NTSTATUS Status;
+ ULONG ResultLength;
+ UCHAR buf[1024];
+ PKEY_VALUE_PARTIAL_INFORMATION Information = (PKEY_VALUE_PARTIAL_INFORMATION)buf;
+
+ RtlInitUnicodeString(&ValueName, RegistryValue);
+ Status =
+ ZwQueryValueKey(RegHandle,
+ &ValueName,
+ KeyValuePartialInformation,
+ Information,
+ sizeof(buf),
+ &ResultLength);
+
+ if (!NT_SUCCESS(Status))
+ return Status;
+ /* IP address is stored as a REG_MULTI_SZ - we only pay attention to the first one though */
+ TI_DbgPrint(MIN_TRACE, ("Information DataLength: 0x%x\n", Information->DataLength));
+
+ UnicodeString.Buffer = (PWCHAR)&Information->Data;
+ UnicodeString.Length = Information->DataLength - sizeof(WCHAR);
+ UnicodeString.MaximumLength = Information->DataLength;
+
+ String->Buffer =
+ (PWCHAR)exAllocatePool( NonPagedPool,
+ UnicodeString.MaximumLength + sizeof(WCHAR) );
+
+ if( !String->Buffer ) return STATUS_NO_MEMORY;
+
+ String->MaximumLength = UnicodeString.MaximumLength;
+ RtlCopyUnicodeString( String, &UnicodeString );
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * Utility to copy and append two unicode strings.
+ *
+ * IN OUT PUNICODE_STRING ResultFirst -> First string and result
+ * IN PUNICODE_STRING Second -> Second string to append
+ * IN BOOL Deallocate -> TRUE: Deallocate First string before
+ * overwriting.
+ *
+ * Returns NTSTATUS.
+ */
+
+NTSTATUS NTAPI AppendUnicodeString(PUNICODE_STRING ResultFirst,
+ PUNICODE_STRING Second,
+ BOOL Deallocate) {
+ NTSTATUS Status;
+ UNICODE_STRING Ustr = *ResultFirst;
+ PWSTR new_string = ExAllocatePoolWithTag
+ (PagedPool,
+ (ResultFirst->Length + Second->Length + sizeof(WCHAR)), TAG_STRING);
+ if( !new_string ) {
+ return STATUS_NO_MEMORY;
+ }
+ memcpy( new_string, ResultFirst->Buffer, ResultFirst->Length );
+ memcpy( new_string + ResultFirst->Length / sizeof(WCHAR),
+ Second->Buffer, Second->Length );
+ if( Deallocate ) RtlFreeUnicodeString(ResultFirst);
+ ResultFirst->Length = Ustr.Length + Second->Length;
+ ResultFirst->MaximumLength = ResultFirst->Length;
+ new_string[ResultFirst->Length / sizeof(WCHAR)] = 0;
+ Status = RtlCreateUnicodeString(ResultFirst,new_string) ?
+ STATUS_SUCCESS : STATUS_NO_MEMORY;
+ ExFreePool(new_string);
+ return Status;
+}
+
+static NTSTATUS CheckForDeviceDesc( PUNICODE_STRING EnumKeyName,
+ PUNICODE_STRING TargetKeyName,
+ PUNICODE_STRING Name,
+ PUNICODE_STRING DeviceDesc ) {
+ UNICODE_STRING RootDevice = { 0 }, LinkageKeyName = { 0 };
+ UNICODE_STRING DescKeyName = { 0 }, Linkage = { 0 };
+ UNICODE_STRING BackSlash = { 0 };
+ HANDLE DescKey = NULL, LinkageKey = NULL;
+ NTSTATUS Status;
+
+ TI_DbgPrint(DEBUG_DATALINK,("EnumKeyName %wZ\n", EnumKeyName));
+
+ RtlInitUnicodeString(&BackSlash, L"\\");
+ RtlInitUnicodeString(&Linkage, L"\\Linkage");
+
+ RtlInitUnicodeString(&DescKeyName, L"");
+ AppendUnicodeString( &DescKeyName, EnumKeyName, FALSE );
+ AppendUnicodeString( &DescKeyName, &BackSlash, TRUE );
+ AppendUnicodeString( &DescKeyName, TargetKeyName, TRUE );
+
+ RtlInitUnicodeString(&LinkageKeyName, L"");
+ AppendUnicodeString( &LinkageKeyName, &DescKeyName, FALSE );
+ AppendUnicodeString( &LinkageKeyName, &Linkage, TRUE );
+
+ Status = OpenRegistryKey( &LinkageKeyName, &LinkageKey );
+ if( !NT_SUCCESS(Status) ) goto cleanup;
+
+ Status = ReadStringFromRegistry( LinkageKey, L"RootDevice", &RootDevice );
+ if( !NT_SUCCESS(Status) ) goto cleanup;
+
+ if( RtlCompareUnicodeString( &RootDevice, Name, TRUE ) == 0 ) {
+ Status = OpenRegistryKey( &DescKeyName, &DescKey );
+ if( !NT_SUCCESS(Status) ) goto cleanup;
+
+ Status = ReadStringFromRegistry( DescKey, L"DriverDesc", DeviceDesc );
+ if( !NT_SUCCESS(Status) ) goto cleanup;
+
+ TI_DbgPrint(DEBUG_DATALINK,("ADAPTER DESC: %wZ\n", DeviceDesc));
+ } else Status = STATUS_UNSUCCESSFUL;
+
+cleanup:
+ RtlFreeUnicodeString( &RootDevice );
+ RtlFreeUnicodeString( &LinkageKeyName );
+ RtlFreeUnicodeString( &DescKeyName );
+ if( LinkageKey ) NtClose( LinkageKey );
+ if( DescKey ) NtClose( DescKey );
+
+ TI_DbgPrint(DEBUG_DATALINK,("Returning %x\n", Status));
+
+ return Status;
+}
+
+static NTSTATUS FindDeviceDescForAdapter( PUNICODE_STRING Name,
+ PUNICODE_STRING DeviceDesc ) {
+ UNICODE_STRING EnumKeyName, TargetKeyName;
+ HANDLE EnumKey;
+ NTSTATUS Status;
+ ULONG i;
+ KEY_BASIC_INFORMATION *Kbio =
+ ExAllocatePool(NonPagedPool, sizeof(KEY_BASIC_INFORMATION));
+ ULONG KbioLength = sizeof(KEY_BASIC_INFORMATION), ResultLength;
+
+ RtlInitUnicodeString
+ (&EnumKeyName, CCS_ROOT L"\\Control\\Class\\" TCPIP_GUID);
+
+ Status = OpenRegistryKey( &EnumKeyName, &EnumKey );
+
+ if( !NT_SUCCESS(Status) )
+ TI_DbgPrint(DEBUG_DATALINK,("Couldn't open Enum key %wZ: %x\n",
+ &EnumKeyName, Status));
+
+ for( i = 0; NT_SUCCESS(Status); i++ ) {
+ Status = ZwEnumerateKey( EnumKey, i, KeyBasicInformation,
+ Kbio, KbioLength, &ResultLength );
+
+ if( Status == STATUS_BUFFER_TOO_SMALL ) {
+ ExFreePool( Kbio );
+ KbioLength = ResultLength;
+ Kbio = ExAllocatePool( NonPagedPool, KbioLength );
+
+ Status = ZwEnumerateKey( EnumKey, i, KeyBasicInformation,
+ Kbio, KbioLength, &ResultLength );
+
+ TI_DbgPrint(DEBUG_DATALINK,("Couldn't enum key child %d\n", i));
+ return Status;
+ }
+
+ if( NT_SUCCESS(Status) ) {
+ TargetKeyName.Length = TargetKeyName.MaximumLength =
+ Kbio->NameLength;
+ TargetKeyName.Buffer = Kbio->Name;
+
+ Status = CheckForDeviceDesc
+ ( &EnumKeyName, &TargetKeyName, Name, DeviceDesc );
+ if( NT_SUCCESS(Status) ) {
+ NtClose( EnumKey );
+ return Status;
+ } else Status = STATUS_SUCCESS;
+ }
+ }
+
+ RtlInitUnicodeString( DeviceDesc, L"" );
+ AppendUnicodeString( DeviceDesc, &TargetKeyName, FALSE );
+ NtClose( EnumKey );
+ return STATUS_UNSUCCESSFUL;
+}
+
+VOID GetName( PUNICODE_STRING RegistryKey,
+ PUNICODE_STRING OutName ) {
+ PWCHAR Ptr;
+ UNICODE_STRING PartialRegistryKey;
+
+ PartialRegistryKey.Buffer =
+ RegistryKey->Buffer + wcslen(CCS_ROOT L"\\Services\\");
+ Ptr = PartialRegistryKey.Buffer;
+
+ while( *Ptr != L'\\' &&
+ ((PCHAR)Ptr) < ((PCHAR)RegistryKey->Buffer) + RegistryKey->Length )
+ Ptr++;
+
+ PartialRegistryKey.Length = PartialRegistryKey.MaximumLength =
+ (Ptr - PartialRegistryKey.Buffer) * sizeof(WCHAR);
+
+ RtlInitUnicodeString( OutName, L"" );
+ AppendUnicodeString( OutName, &PartialRegistryKey, FALSE );
+}
VOID BindAdapter(
PLAN_ADAPTER Adapter,
- PNDIS_STRING RegistryPath)
+ PNDIS_STRING RegistryPath)
/*
* FUNCTION: Binds a LAN adapter to IP layer
* ARGUMENTS:
* bind the adapter to IP layer
*/
{
- INT i;
PIP_INTERFACE IF;
- PIP_ADDRESS Address;
- PNDIS_PACKET Packet;
NDIS_STATUS NdisStatus;
LLIP_BIND_INFO BindInfo;
+ IP_ADDRESS DefaultMask = { 0 };
ULONG Lookahead = LOOKAHEAD_SIZE;
+ NTSTATUS Status;
+ HANDLE RegHandle = 0;
TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
&Lookahead,
sizeof(ULONG));
if (NdisStatus != NDIS_STATUS_SUCCESS) {
- TI_DbgPrint(MID_TRACE, ("Could not set lookahead buffer size (0x%X).\n", NdisStatus));
+ TI_DbgPrint(DEBUG_DATALINK, ("Could not set lookahead buffer size (0x%X).\n", NdisStatus));
return;
}
- /* Allocate packets for NdisTransferData */
- /* FIXME: How many should we allocate? */
- Adapter->TDPackets = NULL;
- for (i = 0; i < 2; i++) {
- Packet = AllocateTDPacket(Adapter);
- if (!Packet) {
- TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
- FreeTDPackets(Adapter);
- return;
- }
- PC(Packet)->Context = Adapter->TDPackets;
- Adapter->TDPackets = Packet;
- }
-
/* Bind the adapter to IP layer */
BindInfo.Context = Adapter;
BindInfo.HeaderSize = Adapter->HeaderSize;
BindInfo.Transmit = LANTransmit;
IF = IPCreateInterface(&BindInfo);
+
if (!IF) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
- FreeTDPackets(Adapter);
return;
}
- {
- /*
- * Query per-adapter configuration from the registry
- * In case anyone is curious: there *is* an Ndis configuration api
- * for this sort of thing, but it doesn't really support things like
- * REG_MULTI_SZ very well, and there is a note in the DDK that says that
- * protocol drivers developed for win2k and above just use the native
- * services (ZwOpenKey, etc).
- */
-
- OBJECT_ATTRIBUTES Attributes;
- HANDLE RegHandle;
- NTSTATUS Status;
- UNICODE_STRING ValueName;
- UCHAR buf[1024];
- PKEY_VALUE_PARTIAL_INFORMATION Information = (PKEY_VALUE_PARTIAL_INFORMATION)buf;
- ULONG ResultLength;
- ANSI_STRING AnsiAddress;
- UNICODE_STRING UnicodeAddress;
- ULONG AnsiLen;
-
- InitializeObjectAttributes(&Attributes, RegistryPath, OBJ_CASE_INSENSITIVE, 0, 0);
- Status = ZwOpenKey(&RegHandle, GENERIC_READ, &Attributes);
-
- if(!NT_SUCCESS(Status))
- {
- TI_DbgPrint(MIN_TRACE, ("Unable to open protocol-specific registry key: 0x%x\n", Status));
-
- /* XXX how do we proceed? No ip address, no parameters... do we guess? */
- FreeTDPackets(Adapter);
- IPDestroyInterface(Adapter->Context);
- return;
- }
-
- RtlInitUnicodeString(&ValueName, L"IPAddress");
- ZwQueryValueKey(RegHandle, &ValueName, KeyValuePartialInformation, Information, sizeof(buf), &ResultLength);
- ZwClose(RegHandle);
-
- /* IP address is stored as a REG_MULTI_SZ - we only pay attention to the first one though */
- TI_DbgPrint(MIN_TRACE, ("Information DataLength: 0x%x\n", Information->DataLength));
-
- UnicodeAddress.Buffer = (PWCHAR)&Information->Data;
- UnicodeAddress.Length = Information->DataLength;
- UnicodeAddress.MaximumLength = Information->DataLength;
-
- AnsiLen = RtlUnicodeStringToAnsiSize(&UnicodeAddress);
- if(!AnsiLen)
- {
- TI_DbgPrint(MIN_TRACE, ("Unable to calculate address length\n"));
- FreeTDPackets(Adapter);
- IPDestroyInterface(Adapter->Context);
- return;
- }
-
- AnsiAddress.Buffer = ExAllocatePoolWithTag(PagedPool, AnsiLen, 0x01020304);
- if(!AnsiAddress.Buffer)
- {
- TI_DbgPrint(MIN_TRACE, ("ExAllocatePoolWithTag() failed.\n"));
- FreeTDPackets(Adapter);
- IPDestroyInterface(Adapter->Context);
- return;
- }
- AnsiAddress.Length = AnsiLen;
- AnsiAddress.MaximumLength = AnsiLen;
-
- Status = RtlUnicodeStringToAnsiString(&AnsiAddress, &UnicodeAddress, FALSE);
- if (!NT_SUCCESS(Status))
- {
- TI_DbgPrint(MIN_TRACE, ("RtlUnicodeStringToAnsiString() failed with Status 0x%lx.\n", Status));
- FreeTDPackets(Adapter);
- IPDestroyInterface(Adapter->Context);
- return;
- }
-
- AnsiAddress.Buffer[AnsiAddress.Length] = 0;
- Address = AddrBuildIPv4(inet_addr(AnsiAddress.Buffer));
- if (!Address) {
- TI_DbgPrint(MIN_TRACE, ("AddrBuildIPv4() failed.\n"));
- FreeTDPackets(Adapter);
- IPDestroyInterface(Adapter->Context);
- return;
- }
-
- TI_DbgPrint(MID_TRACE, ("--> Our IP address on this interface: '%s'\n", A2S(Address)));
- }
-
- /* Create a net table entry for this interface */
- if (!IPCreateNTE(IF, Address, 8)) {
- TI_DbgPrint(MIN_TRACE, ("IPCreateNTE() failed.\n"));
- FreeTDPackets(Adapter);
- IPDestroyInterface(IF);
- return;
+ /*
+ * Query per-adapter configuration from the registry
+ * In case anyone is curious: there *is* an Ndis configuration api
+ * for this sort of thing, but it doesn't really support things like
+ * REG_MULTI_SZ very well, and there is a note in the DDK that says that
+ * protocol drivers developed for win2k and above just use the native
+ * services (ZwOpenKey, etc).
+ */
+
+ GetName( RegistryPath, &IF->Name );
+
+ Status = OpenRegistryKey( RegistryPath, &RegHandle );
+
+ if(NT_SUCCESS(Status)) {
+ Status = FindDeviceDescForAdapter( &IF->Name, &IF->Description );
+ TI_DbgPrint(DEBUG_DATALINK,("Adapter Description: %wZ\n",
+ &IF->Description));
}
- /* Reference the interface for the NTE. The reference
- for the address is just passed on to the NTE */
- ReferenceObject(IF);
+ DefaultMask.Type = IP_ADDRESS_V4;
+
+ IF->Unicast = DefaultMask;
+ IF->Netmask = DefaultMask;
+
+ IF->Broadcast.Type = IP_ADDRESS_V4;
+ IF->Broadcast.Address.IPv4Address =
+ IF->Unicast.Address.IPv4Address |
+ ~IF->Netmask.Address.IPv4Address;
+
+ TI_DbgPrint(DEBUG_DATALINK,("BCAST(IF) %s\n", A2S(&IF->Broadcast)));
+
+ /* Get maximum link speed */
+ NdisStatus = NDISCall(Adapter,
+ NdisRequestQueryInformation,
+ OID_GEN_LINK_SPEED,
+ &IF->Speed,
+ sizeof(UINT));
+
+ if( !NT_SUCCESS(NdisStatus) )
+ IF->Speed = IP_DEFAULT_LINK_SPEED;
/* Register interface with IP layer */
IPRegisterInterface(IF);
OID_GEN_CURRENT_PACKET_FILTER,
&Adapter->PacketFilter,
sizeof(UINT));
+
if (NdisStatus != NDIS_STATUS_SUCCESS) {
- TI_DbgPrint(MID_TRACE, ("Could not set packet filter (0x%X).\n", NdisStatus));
- FreeTDPackets(Adapter);
+ TI_DbgPrint(DEBUG_DATALINK, ("Could not set packet filter (0x%X).\n", NdisStatus));
IPDestroyInterface(IF);
return;
}
Adapter->Context = IF;
-
Adapter->State = LAN_STATE_STARTED;
}
IPUnregisterInterface(IF);
IPDestroyInterface(IF);
-
- /* Free transfer data packets */
- FreeTDPackets(Adapter);
}
}
NDIS_STATUS LANRegisterAdapter(
PNDIS_STRING AdapterName,
- PNDIS_STRING RegistryPath)
+ PNDIS_STRING RegistryPath)
/*
* FUNCTION: Registers protocol with an NDIS adapter
* ARGUMENTS:
PLAN_ADAPTER IF;
NDIS_STATUS NdisStatus;
NDIS_STATUS OpenStatus;
- PNDIS_CONFIGURATION_PARAMETER Parameter;
UINT MediaIndex;
NDIS_MEDIUM MediaArray[MAX_MEDIA];
UINT AddressOID;
TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
- IF = ExAllocatePool(NonPagedPool, sizeof(LAN_ADAPTER));
+ IF = exAllocatePool(NonPagedPool, sizeof(LAN_ADAPTER));
if (!IF) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return NDIS_STATUS_RESOURCES;
if (NdisStatus == NDIS_STATUS_PENDING)
KeWaitForSingleObject(&IF->Event, UserRequest, KernelMode, FALSE, NULL);
else if (NdisStatus != NDIS_STATUS_SUCCESS) {
- ExFreePool(IF);
+ exFreePool(IF);
return NdisStatus;
}
IF->HeaderSize = sizeof(ETH_HEADER);
IF->MinFrameSize = 60;
AddressOID = OID_802_3_CURRENT_ADDRESS;
- IF->PacketFilter =
+ IF->PacketFilter =
NDIS_PACKET_TYPE_BROADCAST |
NDIS_PACKET_TYPE_DIRECTED |
NDIS_PACKET_TYPE_MULTICAST;
default:
/* Unsupported media */
TI_DbgPrint(MIN_TRACE, ("Unsupported media.\n"));
- ExFreePool(IF);
+ exFreePool(IF);
return NDIS_STATUS_NOT_SUPPORTED;
}
&IF->MTU,
sizeof(UINT));
if (NdisStatus != NDIS_STATUS_SUCCESS) {
- ExFreePool(IF);
+ exFreePool(IF);
return NdisStatus;
}
sizeof(UINT));
if (NdisStatus != NDIS_STATUS_SUCCESS) {
TI_DbgPrint(MIN_TRACE, ("Query for maximum packet size failed.\n"));
- ExFreePool(IF);
+ exFreePool(IF);
return NdisStatus;
}
IF->HWAddressLength);
if (NdisStatus != NDIS_STATUS_SUCCESS) {
TI_DbgPrint(MIN_TRACE, ("Query for current hardware address failed.\n"));
- ExFreePool(IF);
+ exFreePool(IF);
return NdisStatus;
}
sizeof(UINT));
if (NdisStatus != NDIS_STATUS_SUCCESS) {
TI_DbgPrint(MIN_TRACE, ("Query for maximum link speed failed.\n"));
- ExFreePool(IF);
+ exFreePool(IF);
return NdisStatus;
}
/* Unbind adapter from IP layer */
UnbindAdapter(Adapter);
- KeAcquireSpinLock(&Adapter->Lock, &OldIrql);
+ TcpipAcquireSpinLock(&Adapter->Lock, &OldIrql);
NdisHandle = Adapter->NdisHandle;
if (NdisHandle) {
Adapter->NdisHandle = NULL;
- KeReleaseSpinLock(&Adapter->Lock, OldIrql);
+ TcpipReleaseSpinLock(&Adapter->Lock, OldIrql);
NdisCloseAdapter(&NdisStatus, NdisHandle);
if (NdisStatus == NDIS_STATUS_PENDING) {
- KeWaitForSingleObject(&Adapter->Event,
- UserRequest,
- KernelMode,
- FALSE,
- NULL);
+ TcpipWaitForSingleObject(&Adapter->Event,
+ UserRequest,
+ KernelMode,
+ FALSE,
+ NULL);
NdisStatus = Adapter->NdisStatus;
}
} else
- KeReleaseSpinLock(&Adapter->Lock, OldIrql);
+ TcpipReleaseSpinLock(&Adapter->Lock, OldIrql);
FreeAdapter(Adapter);
ProtChars.CloseAdapterCompleteHandler = ProtocolCloseAdapterComplete;
ProtChars.ResetCompleteHandler = ProtocolResetComplete;
ProtChars.RequestCompleteHandler = ProtocolRequestComplete;
- ProtChars.u2.SendCompleteHandler = ProtocolSendComplete;
- ProtChars.u3.TransferDataCompleteHandler = ProtocolTransferDataComplete;
- ProtChars.u4.ReceiveHandler = ProtocolReceive;
+ ProtChars.SendCompleteHandler = ProtocolSendComplete;
+ ProtChars.TransferDataCompleteHandler = ProtocolTransferDataComplete;
+ ProtChars.ReceiveHandler = ProtocolReceive;
ProtChars.ReceiveCompleteHandler = ProtocolReceiveComplete;
ProtChars.StatusHandler = ProtocolStatus;
ProtChars.StatusCompleteHandler = ProtocolStatusComplete;
ProtChars.BindAdapterHandler = ProtocolBindAdapter;
- /* Try to register protocol */
+ /* Try to register protocol */
NdisRegisterProtocol(&NdisStatus,
&NdisProtocolHandle,
&ProtChars,
sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
if (NdisStatus != NDIS_STATUS_SUCCESS)
- {
- TI_DbgPrint(MID_TRACE, ("NdisRegisterProtocol failed, status 0x%x\n", NdisStatus));
+ {
+ TI_DbgPrint(DEBUG_DATALINK, ("NdisRegisterProtocol failed, status 0x%x\n", NdisStatus));
return (NTSTATUS)NdisStatus;
- }
+ }
ProtocolRegistered = TRUE;
PLAN_ADAPTER Current;
KIRQL OldIrql;
- KeAcquireSpinLock(&AdapterListLock, &OldIrql);
+ TcpipAcquireSpinLock(&AdapterListLock, &OldIrql);
/* Search the list and remove every adapter we find */
CurrentEntry = AdapterListHead.Flink;
while (CurrentEntry != &AdapterListHead) {
NextEntry = CurrentEntry->Flink;
- Current = CONTAINING_RECORD(CurrentEntry, LAN_ADAPTER, ListEntry);
+ Current = CONTAINING_RECORD(CurrentEntry, LAN_ADAPTER, ListEntry);
/* Unregister it */
LANUnregisterAdapter(Current);
CurrentEntry = NextEntry;
}
- KeReleaseSpinLock(&AdapterListLock, OldIrql);
+ TcpipReleaseSpinLock(&AdapterListLock, OldIrql);
NdisDeregisterProtocol(&NdisStatus, NdisProtocolHandle);
ProtocolRegistered = FALSE;
}
}
+VOID LANStartup() {
+ InitializeListHead( &LanSendCompleteList );
+ KeInitializeSpinLock( &LanSendCompleteLock );
+}
+
+VOID LANShutdown() {
+ KIRQL OldIrql;
+ PLAN_WQ_ITEM WorkItem;
+ PLIST_ENTRY ListEntry;
+
+ KeAcquireSpinLock( &LanSendCompleteLock, &OldIrql );
+ while( !IsListEmpty( &LanSendCompleteList ) ) {
+ ListEntry = RemoveHeadList( &LanSendCompleteList );
+ WorkItem = CONTAINING_RECORD(ListEntry, LAN_WQ_ITEM, ListEntry);
+ FreeNdisPacket( WorkItem->Packet );
+ ExFreePool( WorkItem );
+ }
+ KeReleaseSpinLock( &LanSendCompleteLock, OldIrql );
+}
+
/* EOF */