#include "ndissys.h"
#include "efilter.h"
-#ifdef DBG
#include <buffer.h>
-#endif /* DBG */
-
-#undef NdisMSendComplete
-VOID
-EXPORT
-NdisMSendComplete(
- IN NDIS_HANDLE MiniportAdapterHandle,
- IN PNDIS_PACKET Packet,
- IN NDIS_STATUS Status);
-
-/* Root of the scm database */
-#define SERVICES_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
/*
* Define to 1 to get a debugger breakpoint at the end of NdisInitializeWrapper
MiniDisplayPacket(
PNDIS_PACKET Packet)
{
-#ifdef DBG
+#if DBG
ULONG i, Length;
UCHAR Buffer[64];
if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
PVOID LookaheadBuffer,
UINT LookaheadBufferSize)
{
-#ifdef DBG
+#if DBG
if ((DebugTraceLevel & DEBUG_PACKET) > 0) {
ULONG i, Length;
PUCHAR p;
if (CurrentEntry == &Adapter->ProtocolListHead)
{
- NDIS_DbgPrint(DEBUG_MINIPORT, ("WARNING: No upper protocol layer.\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("WARNING: No upper protocol layer.\n"));
}
while (CurrentEntry != &Adapter->ProtocolListHead)
AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterBinding = %x\n", AdapterBinding));
- KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
-
-#ifdef DBG
- if(!AdapterBinding)
- {
- NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding was null\n"));
- break;
- }
-
- if(!AdapterBinding->ProtocolBinding)
- {
- NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding was null\n"));
- break;
- }
-
- if(!AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)
- {
- NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding->Chars.ReceiveHandler was null\n"));
- break;
- }
-#endif
-
NDIS_DbgPrint
(MID_TRACE,
("XXX (%x) %x %x %x %x %x %x %x XXX\n",
LookaheadBufferSize,
PacketSize);
- KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
-
CurrentEntry = CurrentEntry->Flink;
}
}
\f
VOID NTAPI
MiniIndicateReceivePacket(
- IN NDIS_HANDLE Miniport,
+ IN NDIS_HANDLE MiniportAdapterHandle,
IN PPNDIS_PACKET PacketArray,
IN UINT NumberOfPackets)
/*
* FUNCTION: receives miniport packet array indications
* ARGUMENTS:
- * Miniport: Miniport handle for the adapter
+ * MiniportAdapterHandle: Miniport handle for the adapter
* PacketArray: pointer to a list of packet pointers to indicate
* NumberOfPackets: number of packets to indicate
- * NOTES:
- * - This currently is a big temporary hack. In the future this should
- * call ProtocolReceivePacket() on each bound protocol if it exists.
- * For now it just mimics NdisMEthIndicateReceive.
+ *
*/
{
+ PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
+ PLIST_ENTRY CurrentEntry;
+ PADAPTER_BINDING AdapterBinding;
+ KIRQL OldIrql;
UINT i;
- for(i = 0; i < NumberOfPackets; i++)
- {
- PCHAR PacketBuffer = 0;
- UINT PacketLength = 0;
- PNDIS_BUFFER NdisBuffer = 0;
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
-#define PACKET_TAG (('k' << 24) + ('P' << 16) + ('D' << 8) + 'N')
+ CurrentEntry = Adapter->ProtocolListHead.Flink;
+
+ while (CurrentEntry != &Adapter->ProtocolListHead)
+ {
+ AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
+
+ for (i = 0; i < NumberOfPackets; i++)
+ {
+ if (AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler &&
+ NDIS_GET_PACKET_STATUS(PacketArray[i]) != NDIS_STATUS_RESOURCES)
+ {
+ (*AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler)(
+ AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
+ PacketArray[i]);
+ }
+ else
+ {
+ UINT FirstBufferLength, TotalBufferLength, LookAheadSize, HeaderSize;
+ PNDIS_BUFFER NdisBuffer;
+ PVOID NdisBufferVA, LookAheadBuffer;
+ NDIS_STATUS NdisStatus;
+
+
+ NdisGetFirstBufferFromPacket(PacketArray[i],
+ &NdisBuffer,
+ &NdisBufferVA,
+ &FirstBufferLength,
+ &TotalBufferLength);
+
+ HeaderSize = NDIS_GET_PACKET_HEADER_SIZE(PacketArray[i]);
+
+ if (Adapter->NdisMiniportBlock.CurrentLookahead < (TotalBufferLength - HeaderSize))
+ {
+ LookAheadSize = Adapter->NdisMiniportBlock.CurrentLookahead;
+ }
+ else
+ {
+ LookAheadSize = TotalBufferLength - HeaderSize;
+ }
- NdisAllocateMemoryWithTag((PVOID)&PacketBuffer, 1518, PACKET_TAG);
- if(!PacketBuffer)
- {
- NDIS_DbgPrint(MIN_TRACE, ("insufficient resources\n"));
- return;
- }
- NdisQueryPacket(PacketArray[i], NULL, NULL, &NdisBuffer, NULL);
+ LookAheadBuffer = ExAllocatePool(NonPagedPool, LookAheadSize);
+ if (!LookAheadBuffer)
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate lookahead buffer!\n"));
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+ return;
+ }
- while(NdisBuffer)
- {
- PNDIS_BUFFER CurrentBuffer;
- PVOID BufferVa;
- UINT BufferLen;
+ CopyBufferChainToBuffer(LookAheadBuffer,
+ NdisBuffer,
+ HeaderSize,
+ LookAheadSize);
- NdisQueryBuffer(NdisBuffer, &BufferVa, &BufferLen);
- memcpy(PacketBuffer + PacketLength, BufferVa, BufferLen);
- PacketLength += BufferLen;
+ NdisStatus = (*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
+ AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
+ AdapterBinding->NdisOpenBlock.MacHandle,
+ NdisBufferVA,
+ HeaderSize,
+ LookAheadBuffer,
+ LookAheadSize,
+ TotalBufferLength - HeaderSize);
- CurrentBuffer = NdisBuffer;
- NdisGetNextBuffer(CurrentBuffer, &NdisBuffer);
- }
+ NDIS_SET_PACKET_STATUS(PacketArray[i], NdisStatus);
- NDIS_DbgPrint(MID_TRACE, ("indicating a %d-byte packet\n", PacketLength));
+ ExFreePool(LookAheadBuffer);
+ }
+ }
- MiniIndicateData(Miniport, NULL, PacketBuffer, 14, PacketBuffer+14, PacketLength-14, PacketLength-14);
+ CurrentEntry = CurrentEntry->Flink;
+ }
- NdisFreeMemory(PacketBuffer, 0, 0);
- }
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
}
\f
IN NDIS_STATUS Status,
IN BOOLEAN AddressingReset)
{
- UNIMPLEMENTED
-}
+ PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
+ PLIST_ENTRY CurrentEntry;
+ PADAPTER_BINDING AdapterBinding;
+ KIRQL OldIrql;
+ MiniEndRequest(Adapter, NdisWorkItemResetRequested);
+
+ if (AddressingReset)
+ MiniDoAddressingReset(Adapter);
+
+ NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
+ NdisMIndicateStatusComplete(Adapter);
+
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+
+ CurrentEntry = Adapter->ProtocolListHead.Flink;
+
+ while (CurrentEntry != &Adapter->ProtocolListHead)
+ {
+ AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
+
+ (*AdapterBinding->ProtocolBinding->Chars.ResetCompleteHandler)(
+ AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
+ Status);
+
+ CurrentEntry = CurrentEntry->Flink;
+ }
+
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+}
-\f
VOID NTAPI
MiniRequestComplete(
- IN PNDIS_MINIPORT_BLOCK Adapter,
- IN PNDIS_REQUEST Request,
+ IN NDIS_HANDLE MiniportAdapterHandle,
IN NDIS_STATUS Status)
{
- PNDIS_REQUEST_MAC_BLOCK MacBlock = (PNDIS_REQUEST_MAC_BLOCK)Request->MacReserved;
+ PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
+ PNDIS_REQUEST Request;
+ PNDIS_REQUEST_MAC_BLOCK MacBlock;
+ KIRQL OldIrql;
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+ Request = Adapter->NdisMiniportBlock.PendingRequest;
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+
+ MiniEndRequest(Adapter, NdisWorkItemRequest);
+
+ MacBlock = (PNDIS_REQUEST_MAC_BLOCK)Request->MacReserved;
+
if( MacBlock->Binding->RequestCompleteHandler ) {
(*MacBlock->Binding->RequestCompleteHandler)(
MacBlock->Binding->ProtocolBindingContext,
}
}
+VOID NTAPI
+MiniIndicateComplete(
+ IN NDIS_HANDLE MiniportAdapterHandle,
+ IN PNDIS_PACKET Packet,
+ IN NDIS_STATUS Status)
+{
+ PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
+
+ MiniEndRequest(MiniportAdapterHandle, NdisWorkItemSendLoopback);
+
+ (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
+ AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
+ Packet,
+ Status);
+}
+
VOID NTAPI
MiniSendComplete(
IN NDIS_HANDLE MiniportAdapterHandle,
* Status = Status of send operation
*/
{
+ PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
PADAPTER_BINDING AdapterBinding;
+ KIRQL OldIrql;
+ PSCATTER_GATHER_LIST SGList;
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
- AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
+ AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
+
+ if (Adapter->NdisMiniportBlock.ScatterGatherListSize != 0)
+ {
+ NDIS_DbgPrint(MAX_TRACE, ("Freeing Scatter/Gather list\n"));
+
+ SGList = NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
+ ScatterGatherListPacketInfo);
+
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+
+ Adapter->NdisMiniportBlock.SystemAdapterObject->
+ DmaOperations->PutScatterGatherList(
+ Adapter->NdisMiniportBlock.SystemAdapterObject,
+ SGList,
+ TRUE);
+
+ KeLowerIrql(OldIrql);
+
+ NDIS_PER_PACKET_INFO_FROM_PACKET(Packet,
+ ScatterGatherListPacketInfo) = NULL;
+ }
+
+ MiniEndRequest(Adapter, NdisWorkItemSend);
(*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
Status);
}
+NDIS_STATUS
+SignalQueue(PLOGICAL_ADAPTER Adapter)
+{
+ PIO_WORKITEM WorkItem = IoAllocateWorkItem(Adapter->NdisMiniportBlock.DeviceObject);
+
+ ASSERT(WorkItem);
+ if (!WorkItem) return NDIS_STATUS_RESOURCES;
+
+ IoQueueWorkItem(WorkItem,
+ MiniportWorker,
+ DelayedWorkQueue,
+ WorkItem);
+
+ return NDIS_STATUS_SUCCESS;
+}
VOID NTAPI
MiniSendResourcesAvailable(
IN NDIS_HANDLE MiniportAdapterHandle)
{
-/*
- UNIMPLEMENTED
-*/
+ SignalQueue(MiniportAdapterHandle);
}
-
VOID NTAPI
MiniTransferDataComplete(
IN NDIS_HANDLE MiniportAdapterHandle,
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
- AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
+ AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[1];
- (*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
+ (*AdapterBinding->ProtocolBinding->Chars.TransferDataCompleteHandler)(
AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
Packet,
- Status);
+ Status,
+ BytesTransferred);
}
\f
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
-#ifdef DBG
+#if DBG
if(!Adapter)
{
- NDIS_DbgPrint(MID_TRACE, ("Adapter object was null\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("Adapter object was null\n"));
return FALSE;
}
if(!Packet)
{
- NDIS_DbgPrint(MID_TRACE, ("Packet was null\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("Packet was null\n"));
return FALSE;
}
#endif
if (!NdisBuffer)
{
- NDIS_DbgPrint(MID_TRACE, ("Packet contains no buffers.\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("Packet contains no buffers.\n"));
return FALSE;
}
if (BufferLength < Length)
{
- NDIS_DbgPrint(MID_TRACE, ("Buffer is too small.\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("Buffer is too small.\n"));
return FALSE;
}
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
- if(IsListEmpty(&AdapterListHead))
- {
- NDIS_DbgPrint(DEBUG_MINIPORT, ("No registered miniports for protocol to bind to\n"));
- return NULL;
- }
-
KeAcquireSpinLock(&AdapterListLock, &OldIrql);
{
CurrentEntry = AdapterListHead.Flink;
}
else
{
- NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving (adapter not found).\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("Leaving (adapter not found for %wZ).\n", AdapterName));
}
return Adapter;
}
-\f
+NDIS_STATUS
+MiniSetInformation(
+ PLOGICAL_ADAPTER Adapter,
+ NDIS_OID Oid,
+ ULONG Size,
+ PVOID Buffer,
+ PULONG BytesRead)
+{
+ NDIS_STATUS NdisStatus;
+ PNDIS_REQUEST NdisRequest;
+
+ NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
+
+ NdisRequest = ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
+ if (!NdisRequest) {
+ NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ RtlZeroMemory(NdisRequest, sizeof(NDIS_REQUEST));
+
+ NdisRequest->RequestType = NdisRequestSetInformation;
+ NdisRequest->DATA.SET_INFORMATION.Oid = Oid;
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer = Buffer;
+ NdisRequest->DATA.SET_INFORMATION.InformationBufferLength = Size;
+
+ NdisStatus = MiniBeginRequest(Adapter, NdisWorkItemRequest, NdisRequest);
+ if (!NT_SUCCESS(NdisStatus))
+ return NdisStatus;
+
+ NdisStatus = MiniDoRequest(Adapter, NdisRequest);
+
+ /* FIXME: Wait in pending case! */
+ if (NdisStatus != NDIS_STATUS_PENDING)
+ MiniEndRequest(Adapter, NdisWorkItemRequest);
+
+ ASSERT(NdisStatus != NDIS_STATUS_PENDING);
+
+ *BytesRead = NdisRequest->DATA.SET_INFORMATION.BytesRead;
+
+ ExFreePool(NdisRequest);
+
+ return NdisStatus;
+}
+
NDIS_STATUS
MiniQueryInformation(
PLOGICAL_ADAPTER Adapter,
* Size = Size of the passed buffer
* Buffer = Buffer for the output
* BytesWritten = Address of buffer to place number of bytes written
- * NOTES:
- * If the specified buffer is too small, a new buffer is allocated,
- * and the query is attempted again
* RETURNS:
* Status of operation
- * TODO:
- * Is there any way to use the buffer provided by the protocol?
*/
{
NDIS_STATUS NdisStatus;
- ULONG BytesNeeded;
+ PNDIS_REQUEST NdisRequest;
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
- /* call the miniport's queryinfo handler */
- NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
- Adapter->NdisMiniportBlock.MiniportAdapterContext,
- Oid,
- Buffer,
- Size,
- BytesWritten,
- &BytesNeeded);
+ NdisRequest = ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
+ if (!NdisRequest) {
+ NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ RtlZeroMemory(NdisRequest, sizeof(NDIS_REQUEST));
+
+ NdisRequest->RequestType = NdisRequestQueryInformation;
+ NdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = Buffer;
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = Size;
+
+ NdisStatus = MiniBeginRequest(Adapter, NdisWorkItemRequest, NdisRequest);
+ if (!NT_SUCCESS(NdisStatus))
+ return NdisStatus;
+
+ NdisStatus = MiniDoRequest(Adapter, NdisRequest);
/* FIXME: Wait in pending case! */
+ if (NdisStatus != NDIS_STATUS_PENDING)
+ MiniEndRequest(Adapter, NdisWorkItemRequest);
+
+ ASSERT(NdisStatus != NDIS_STATUS_PENDING);
+
+ *BytesWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
+
+ ExFreePool(NdisRequest);
return NdisStatus;
}
-\f
+BOOLEAN
+MiniCheckForHang( PLOGICAL_ADAPTER Adapter )
+/*
+ * FUNCTION: Checks to see if the miniport is hung
+ * ARGUMENTS:
+ * Adapter = Pointer to the logical adapter object
+ * RETURNS:
+ * TRUE if the miniport is hung
+ * FALSE if the miniport is not hung
+ */
+{
+ BOOLEAN Ret = FALSE;
+
+ if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)
+ Ret = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)(
+ Adapter->NdisMiniportBlock.MiniportAdapterContext);
+
+ return Ret;
+}
+
+VOID
+MiniDoAddressingReset(PLOGICAL_ADAPTER Adapter)
+{
+ ULONG BytesRead;
+
+ MiniSetInformation(Adapter,
+ OID_GEN_CURRENT_LOOKAHEAD,
+ sizeof(ULONG),
+ &Adapter->NdisMiniportBlock.CurrentLookahead,
+ &BytesRead);
+
+ /* FIXME: Set more stuff */
+}
+
NDIS_STATUS
-FASTCALL
-MiniQueueWorkItem(
- PLOGICAL_ADAPTER Adapter,
- NDIS_WORK_ITEM_TYPE WorkItemType,
- PVOID WorkItemContext)
+MiniReset(
+ PLOGICAL_ADAPTER Adapter)
/*
- * FUNCTION: Queues a work item for execution at a later time
+ * FUNCTION: Resets the miniport
* ARGUMENTS:
- * Adapter = Pointer to the logical adapter object to queue work item on
- * WorkItemType = Type of work item to queue
- * WorkItemContext = Pointer to context information for work item
- * NOTES:
- * Adapter lock must be held when called
+ * Adapter = Pointer to the logical adapter object
* RETURNS:
- * Status of operation
+ * Status of the operation
*/
{
- PNDIS_MINIPORT_WORK_ITEM Item;
+ NDIS_STATUS Status;
+ BOOLEAN AddressingReset = TRUE;
- NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+ Status = MiniBeginRequest(Adapter, NdisWorkItemResetRequested, NULL);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_START, NULL, 0);
+ NdisMIndicateStatusComplete(Adapter);
+
+ Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
+ Adapter->NdisMiniportBlock.MiniportAdapterContext,
+ &AddressingReset);
- ASSERT(Adapter);
- ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
+ if (Status != NDIS_STATUS_PENDING) {
+ if (AddressingReset)
+ MiniDoAddressingReset(Adapter);
- Item = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
- if (Item == NULL)
+ MiniEndRequest(Adapter, NdisWorkItemResetRequested);
+
+ NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
+ NdisMIndicateStatusComplete(Adapter);
+ }
+
+ return Status;
+}
+
+VOID NTAPI
+MiniportHangDpc(
+ PKDPC Dpc,
+ PVOID DeferredContext,
+ PVOID SystemArgument1,
+ PVOID SystemArgument2)
+{
+ PLOGICAL_ADAPTER Adapter = DeferredContext;
+
+ if (MiniCheckForHang(Adapter)) {
+ NDIS_DbgPrint(MIN_TRACE, ("Miniport detected adapter hang\n"));
+ MiniReset(Adapter);
+ }
+}
+
+NDIS_STATUS
+MiniBeginRequest(
+ PLOGICAL_ADAPTER Adapter,
+ NDIS_WORK_ITEM_TYPE WorkItemType,
+ PVOID WorkItemContext)
+{
+ KIRQL OldIrql;
+ BOOLEAN QueueBusy;
+ PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
+ PSINGLE_LIST_ENTRY CurrentEntry;
+
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+
+ QueueBusy = (Adapter->NdisMiniportBlock.WorkQueue[WorkItemType].Next != NULL);
+
+ MiniportWorkItem = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
+ if (!MiniportWorkItem)
{
NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
return NDIS_STATUS_RESOURCES;
}
- Item->WorkItemType = WorkItemType;
- Item->WorkItemContext = WorkItemContext;
+ MiniportWorkItem->WorkItemType = WorkItemType;
+ MiniportWorkItem->WorkItemContext = WorkItemContext;
+ MiniportWorkItem->Link.Next = NULL;
- /* safe due to adapter lock held */
- Item->Link.Next = NULL;
- if (!Adapter->WorkQueueHead)
- {
- Adapter->WorkQueueHead = Item;
- Adapter->WorkQueueTail = Item;
- }
- else
- {
- Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item;
- Adapter->WorkQueueTail = Item;
- }
+ CurrentEntry = &Adapter->NdisMiniportBlock.WorkQueue[WorkItemType];
+ while (CurrentEntry->Next)
+ CurrentEntry = CurrentEntry->Next;
- KeInsertQueueDpc(&Adapter->NdisMiniportBlock.DeferredDpc, NULL, NULL);
+ CurrentEntry->Next = (PSINGLE_LIST_ENTRY)MiniportWorkItem;
- return NDIS_STATUS_SUCCESS;
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+
+ if (QueueBusy)
+ NDIS_DbgPrint(MIN_TRACE, ("Queue %d busy!\n", WorkItemType));
+
+ return (QueueBusy ? NDIS_STATUS_PENDING : NDIS_STATUS_SUCCESS);
}
\f
FASTCALL
MiniDequeueWorkItem(
PLOGICAL_ADAPTER Adapter,
- NDIS_WORK_ITEM_TYPE *WorkItemType,
+ NDIS_WORK_ITEM_TYPE WorkItemType,
PVOID *WorkItemContext)
/*
* FUNCTION: Dequeues a work item from the work queue of a logical adapter
* Status of operation
*/
{
- PNDIS_MINIPORT_WORK_ITEM Item;
+ PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
+ KIRQL OldIrql;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
- Item = Adapter->WorkQueueHead;
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+ MiniportWorkItem = (PNDIS_MINIPORT_WORK_ITEM)Adapter->NdisMiniportBlock.WorkQueue[WorkItemType].Next;
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
- if (Item)
+ if (MiniportWorkItem)
{
- /* safe due to adapter lock held */
- Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)Item->Link.Next;
-
- if (Item == Adapter->WorkQueueTail)
- Adapter->WorkQueueTail = NULL;
+ /* This is VERY IMPORTANT! We dequeue the work item AFTER completion */
- *WorkItemType = Item->WorkItemType;
- *WorkItemContext = Item->WorkItemContext;
-
- ExFreePool(Item);
+ *WorkItemContext = MiniportWorkItem->WorkItemContext;
return NDIS_STATUS_SUCCESS;
}
+ else
+ {
+ return NDIS_STATUS_FAILURE;
+ }
+}
- return NDIS_STATUS_FAILURE;
+VOID
+MiniEndRequest(
+ PLOGICAL_ADAPTER Adapter,
+ NDIS_WORK_ITEM_TYPE WorkItemType)
+{
+ KIRQL OldIrql;
+ BOOLEAN QueueBusy;
+ PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
+
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+
+ MiniportWorkItem = (PNDIS_MINIPORT_WORK_ITEM)Adapter->NdisMiniportBlock.WorkQueue[WorkItemType].Next;
+ ASSERT(MiniportWorkItem);
+ Adapter->NdisMiniportBlock.WorkQueue[WorkItemType].Next = MiniportWorkItem->Link.Next;
+ ExFreePool(MiniportWorkItem);
+
+ QueueBusy = (Adapter->NdisMiniportBlock.WorkQueue[WorkItemType].Next != NULL);
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+
+ if (QueueBusy)
+ SignalQueue(Adapter);
}
\f
NDIS_STATUS
MiniDoRequest(
- PNDIS_MINIPORT_BLOCK Adapter,
+ PLOGICAL_ADAPTER Adapter,
PNDIS_REQUEST NdisRequest)
/*
* FUNCTION: Sends a request to a miniport
* Status of operation
*/
{
+ NDIS_STATUS Status;
+ KIRQL OldIrql;
+
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
- Adapter->MediaRequest = NdisRequest;
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+ Adapter->NdisMiniportBlock.PendingRequest = NdisRequest;
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
- switch (NdisRequest->RequestType)
+ if (!Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CoRequestHandler)
{
- case NdisRequestQueryInformation:
- return (*Adapter->DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
- Adapter->MiniportAdapterContext,
- NdisRequest->DATA.QUERY_INFORMATION.Oid,
- NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
- NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
- (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
- (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
- break;
+ switch (NdisRequest->RequestType)
+ {
+ case NdisRequestQueryInformation:
+ Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
+ Adapter->NdisMiniportBlock.MiniportAdapterContext,
+ NdisRequest->DATA.QUERY_INFORMATION.Oid,
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
+ NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
+ (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
+ (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
+ break;
- case NdisRequestSetInformation:
- return (*Adapter->DriverHandle->MiniportCharacteristics.SetInformationHandler)(
- Adapter->MiniportAdapterContext,
- NdisRequest->DATA.SET_INFORMATION.Oid,
- NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
- NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
- (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
- (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
- break;
+ case NdisRequestSetInformation:
+ Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SetInformationHandler)(
+ Adapter->NdisMiniportBlock.MiniportAdapterContext,
+ NdisRequest->DATA.SET_INFORMATION.Oid,
+ NdisRequest->DATA.SET_INFORMATION.InformationBuffer,
+ NdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
+ (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
+ (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
+ break;
- default:
- return NDIS_STATUS_FAILURE;
+ default:
+ NDIS_DbgPrint(MIN_TRACE, ("Bad request type\n"));
+ Status = NDIS_STATUS_FAILURE;
+ }
+ }
+ else
+ {
+ Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CoRequestHandler)(
+ Adapter->NdisMiniportBlock.MiniportAdapterContext,
+ NULL, /* FIXME */
+ NdisRequest);
}
+
+ return Status;
}
\f
/*
* @implemented
*/
-#undef NdisMQueryInformationComplete
+#undef NdisMSetInformationComplete
VOID
EXPORT
-NdisMQueryInformationComplete(
+NdisMSetInformationComplete(
IN NDIS_HANDLE MiniportAdapterHandle,
IN NDIS_STATUS Status)
{
- PNDIS_MINIPORT_BLOCK MiniportBlock =
- (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
- ASSERT(MiniportBlock);
- if( MiniportBlock->QueryCompleteHandler )
- (MiniportBlock->QueryCompleteHandler)(MiniportAdapterHandle, Status);
+ PLOGICAL_ADAPTER Adapter =
+ (PLOGICAL_ADAPTER)MiniportAdapterHandle;
+
+ (Adapter->NdisMiniportBlock.SetCompleteHandler)(MiniportAdapterHandle, Status);
+
+ MiniEndRequest(Adapter, NdisWorkItemRequest);
}
\f
-VOID NTAPI MiniportDpc(
- IN PKDPC Dpc,
- IN PVOID DeferredContext,
- IN PVOID SystemArgument1,
- IN PVOID SystemArgument2)
/*
- * FUNCTION: Deferred routine to handle serialization
- * ARGUMENTS:
- * Dpc = Pointer to DPC object
- * DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
- * SystemArgument1 = Unused
- * SystemArgument2 = Unused
+ * @implemented
*/
+#undef NdisMQueryInformationComplete
+VOID
+EXPORT
+NdisMQueryInformationComplete(
+ IN NDIS_HANDLE MiniportAdapterHandle,
+ IN NDIS_STATUS Status)
+{
+ PLOGICAL_ADAPTER Adapter =
+ (PLOGICAL_ADAPTER)MiniportAdapterHandle;
+
+ (Adapter->NdisMiniportBlock.QueryCompleteHandler)(MiniportAdapterHandle, Status);
+
+ MiniEndRequest(Adapter, NdisWorkItemRequest);
+}
+
+VOID
+NTAPI
+MiniportWorker(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
{
+ PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
+ KIRQL RaiseOldIrql;
NDIS_STATUS NdisStatus;
PVOID WorkItemContext;
NDIS_WORK_ITEM_TYPE WorkItemType;
- PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext);
-
- NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
+ BOOLEAN AddressingReset, NextQueue;
- NdisStatus =
- MiniDequeueWorkItem
- (Adapter, &WorkItemType, &WorkItemContext);
+ IoFreeWorkItem((PIO_WORKITEM)Context);
- if (NdisStatus == NDIS_STATUS_SUCCESS)
- {
- switch (WorkItemType)
+ for (WorkItemType = 0; WorkItemType < NUMBER_OF_WORK_ITEM_TYPES; WorkItemType++)
+ {
+ NextQueue = FALSE;
+ while (!NextQueue && MiniDequeueWorkItem(Adapter, WorkItemType, &WorkItemContext) == NDIS_STATUS_SUCCESS)
+ {
+ switch (WorkItemType)
{
case NdisWorkItemSend:
/*
* called by ProSend when protocols want to send packets to the miniport
*/
-#ifdef DBG
- MiniDisplayPacket((PNDIS_PACKET)WorkItemContext);
-#endif
+
if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
{
- NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
-
- /*
- * XXX assumes single-packet - prolly OK since we'll call something
- * different on multi-packet sends
- */
- (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
- Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
- NdisStatus =
- NDIS_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);
-
- NDIS_DbgPrint(MAX_TRACE, ("back from miniport's SendPackets handler\n"));
+ if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
+ {
+ NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
+ (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
+ Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
+ NdisStatus = NDIS_STATUS_PENDING;
+ }
+ else
+ {
+ /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
+ KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
+ {
+ NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
+ (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)(
+ Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
+ }
+ KeLowerIrql(RaiseOldIrql);
+
+ NdisStatus = NDIS_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);
+ if( NdisStatus == NDIS_STATUS_RESOURCES ) {
+ NextQueue = TRUE;
+ break;
+ }
+ }
}
else
{
- NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
-
- NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
- Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext, 0);
-
- NDIS_DbgPrint(MAX_TRACE, ("back from miniport's Send handler\n"));
+ if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
+ {
+ NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
+ NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
+ Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext,
+ ((PNDIS_PACKET)WorkItemContext)->Private.Flags);
+ NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
+ }
+ else
+ {
+ /* Send is called at DISPATCH_LEVEL for all serialized miniports */
+ KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
+ NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
+ NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
+ Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext,
+ ((PNDIS_PACKET)WorkItemContext)->Private.Flags);
+ NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
+ KeLowerIrql(RaiseOldIrql);
+ if( NdisStatus == NDIS_STATUS_RESOURCES ) {
+ NextQueue = TRUE;
+ break;
+ }
+ }
}
+
if( NdisStatus != NDIS_STATUS_PENDING ) {
- NdisMSendComplete
+ MiniSendComplete
( Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus );
- Adapter->MiniportBusy = FALSE;
}
break;
*/
/* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
NdisStatus = ProIndicatePacket(Adapter, (PNDIS_PACKET)WorkItemContext);
- MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
+
+ if( NdisStatus != NDIS_STATUS_PENDING )
+ MiniIndicateComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
break;
case NdisWorkItemReturnPackets:
break;
case NdisWorkItemResetRequested:
+ NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
+ Adapter->NdisMiniportBlock.MiniportAdapterContext,
+ &AddressingReset);
+
+ if (NdisStatus != NDIS_STATUS_PENDING)
+ MiniResetComplete(Adapter, NdisStatus, AddressingReset);
break;
case NdisWorkItemResetInProgress:
break;
case NdisWorkItemRequest:
- NdisStatus = MiniDoRequest(&Adapter->NdisMiniportBlock, (PNDIS_REQUEST)WorkItemContext);
+ NdisStatus = MiniDoRequest(Adapter, (PNDIS_REQUEST)WorkItemContext);
if (NdisStatus == NDIS_STATUS_PENDING)
break;
{
case NdisRequestQueryInformation:
NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
- MiniRequestComplete( &Adapter->NdisMiniportBlock, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
break;
case NdisRequestSetInformation:
NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
- MiniRequestComplete( &Adapter->NdisMiniportBlock, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
break;
default:
NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n"));
+ MiniEndRequest(Adapter, NdisWorkItemRequest);
break;
}
break;
default:
+ MiniEndRequest(Adapter, WorkItemType);
NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType));
break;
}
- }
+ }
+ }
}
+
\f
VOID
NTAPI
IN PVOID StatusBuffer,
IN UINT StatusBufferSize)
{
- UNIMPLEMENTED
+ PLOGICAL_ADAPTER Adapter = MiniportHandle;
+ PLIST_ENTRY CurrentEntry;
+ PADAPTER_BINDING AdapterBinding;
+ KIRQL OldIrql;
+
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+
+ CurrentEntry = Adapter->ProtocolListHead.Flink;
+
+ while (CurrentEntry != &Adapter->ProtocolListHead)
+ {
+ AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
+
+ (*AdapterBinding->ProtocolBinding->Chars.StatusHandler)(
+ AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
+ GeneralStatus,
+ StatusBuffer,
+ StatusBufferSize);
+
+ CurrentEntry = CurrentEntry->Flink;
+ }
+
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
}
\f
MiniStatusComplete(
IN NDIS_HANDLE MiniportAdapterHandle)
{
- UNIMPLEMENTED
+ PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
+ PLIST_ENTRY CurrentEntry;
+ PADAPTER_BINDING AdapterBinding;
+ KIRQL OldIrql;
+
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+
+ CurrentEntry = Adapter->ProtocolListHead.Flink;
+
+ while (CurrentEntry != &Adapter->ProtocolListHead)
+ {
+ AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
+
+ (*AdapterBinding->ProtocolBinding->Chars.StatusCompleteHandler)(
+ AdapterBinding->NdisOpenBlock.ProtocolBindingContext);
+
+ CurrentEntry = CurrentEntry->Flink;
+ }
+
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
}
\f
/*
- * @unimplemented
+ * @implemented
*/
VOID
EXPORT
NdisMCloseLog(
IN NDIS_HANDLE LogHandle)
{
- UNIMPLEMENTED
+ PNDIS_LOG Log = (PNDIS_LOG)LogHandle;
+ PNDIS_MINIPORT_BLOCK Miniport = Log->Miniport;
+ KIRQL OldIrql;
+
+ NDIS_DbgPrint(MAX_TRACE, ("called: LogHandle 0x%x\n", LogHandle));
+
+ KeAcquireSpinLock(&(Miniport)->Lock, &OldIrql);
+ Miniport->Log = NULL;
+ KeReleaseSpinLock(&(Miniport)->Lock, OldIrql);
+
+ ExFreePool(Log);
}
-\f
/*
- * @unimplemented
+ * @implemented
*/
NDIS_STATUS
EXPORT
IN UINT Size,
OUT PNDIS_HANDLE LogHandle)
{
- UNIMPLEMENTED
+ PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
+ PNDIS_LOG Log;
+ KIRQL OldIrql;
+
+ NDIS_DbgPrint(MAX_TRACE, ("called: MiniportAdapterHandle 0x%x, Size %ld\n", MiniportAdapterHandle, Size));
+
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
- return NDIS_STATUS_FAILURE;
+ if (Adapter->NdisMiniportBlock.Log)
+ {
+ *LogHandle = NULL;
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+ return NDIS_STATUS_FAILURE;
+ }
+
+ Log = ExAllocatePool(NonPagedPool, Size + sizeof(NDIS_LOG));
+ if (!Log)
+ {
+ *LogHandle = NULL;
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ Adapter->NdisMiniportBlock.Log = Log;
+
+ KeInitializeSpinLock(&Log->LogLock);
+
+ Log->Miniport = &Adapter->NdisMiniportBlock;
+ Log->TotalSize = Size;
+ Log->CurrentSize = 0;
+ Log->OutPtr = 0;
+ Log->InPtr = 0;
+ Log->Irp = NULL;
+
+ *LogHandle = Log;
+
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+
+ return NDIS_STATUS_SUCCESS;
}
-\f
/*
* @implemented
*/
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
- if(Adapter->BugcheckContext->ShutdownHandler)
+ if(Adapter->BugcheckContext->ShutdownHandler) {
KeDeregisterBugCheckCallback(Adapter->BugcheckContext->CallbackRecord);
+ IoUnregisterShutdownNotification(Adapter->NdisMiniportBlock.DeviceObject);
+ }
}
-\f
/*
- * @unimplemented
+ * @implemented
*/
VOID
EXPORT
NdisMFlushLog(
IN NDIS_HANDLE LogHandle)
{
- UNIMPLEMENTED
+ PNDIS_LOG Log = (PNDIS_LOG) LogHandle;
+ KIRQL OldIrql;
+
+ NDIS_DbgPrint(MAX_TRACE, ("called: LogHandle 0x%x\n", LogHandle));
+
+ /* Lock object */
+ KeAcquireSpinLock(&Log->LogLock, &OldIrql);
+
+ /* Set buffers size */
+ Log->CurrentSize = 0;
+ Log->OutPtr = 0;
+ Log->InPtr = 0;
+
+ /* Unlock object */
+ KeReleaseSpinLock(&Log->LogLock, OldIrql);
}
/*
- * @unimplemented
+ * @implemented
*/
#undef NdisMIndicateStatus
VOID
IN PVOID StatusBuffer,
IN UINT StatusBufferSize)
{
- UNIMPLEMENTED
+ MiniStatus(MiniportAdapterHandle, GeneralStatus, StatusBuffer, StatusBufferSize);
}
/*
- * @unimplemented
+ * @implemented
*/
#undef NdisMIndicateStatusComplete
VOID
NdisMIndicateStatusComplete(
IN NDIS_HANDLE MiniportAdapterHandle)
{
- UNIMPLEMENTED
+ MiniStatusComplete(MiniportAdapterHandle);
}
\f
*NdisWrapperHandle = NULL;
#if BREAK_ON_MINIPORT_INIT
- __asm__ ("int $3\n");
+ DbgBreakPoint();
#endif
Miniport = ExAllocatePool(NonPagedPool, sizeof(NDIS_M_DRIVER_BLOCK));
* ShutdownHandler: Function to call to handle the bugcheck
* NOTES:
* - I'm not sure about ShutdownContext
- * - FIXME - memory leak below
*/
{
PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportHandle;
- PMINIPORT_BUGCHECK_CONTEXT BugcheckContext = Adapter->BugcheckContext;
+ PMINIPORT_BUGCHECK_CONTEXT BugcheckContext;
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
- if(BugcheckContext)
- return;
-
BugcheckContext = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_BUGCHECK_CONTEXT));
if(!BugcheckContext)
{
BugcheckContext->ShutdownHandler = ShutdownHandler;
BugcheckContext->DriverContext = ShutdownContext;
- /* not sure if this needs to be initialized or not... oh well, it's a leak. */
BugcheckContext->CallbackRecord = ExAllocatePool(NonPagedPool, sizeof(KBUGCHECK_CALLBACK_RECORD));
+ if (!BugcheckContext->CallbackRecord) {
+ ExFreePool(BugcheckContext);
+ return;
+ }
+
+ Adapter->BugcheckContext = BugcheckContext;
+
+ KeInitializeCallbackRecord(BugcheckContext->CallbackRecord);
KeRegisterBugCheckCallback(BugcheckContext->CallbackRecord, NdisIBugcheckCallback,
- BugcheckContext, sizeof(BugcheckContext), (PUCHAR)"Ndis Miniport");
+ BugcheckContext, sizeof(*BugcheckContext), (PUCHAR)"Ndis Miniport");
+
+ IoRegisterShutdownNotification(Adapter->NdisMiniportBlock.DeviceObject);
}
\f
return NdisStatus;
}
-#ifdef DBG
+#if DBG
{
/* 802.3 only */
return NdisStatus;
}
- NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.CurrentLookahead));
+ NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_SEND_PACKETS, sizeof(ULONG),
+ &Adapter->NdisMiniportBlock.MaxSendPackets, &BytesWritten);
- if (Adapter->NdisMiniportBlock.MaximumLookahead != 0)
+ if (NdisStatus != NDIS_STATUS_SUCCESS)
{
- Adapter->LookaheadLength = Adapter->NdisMiniportBlock.MaximumLookahead + Adapter->MediumHeaderSize;
- Adapter->LookaheadBuffer = ExAllocatePool(NonPagedPool, Adapter->LookaheadLength);
+ NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_SEND_PACKETS failed. NdisStatus (0x%X).\n", NdisStatus));
- if (!Adapter->LookaheadBuffer)
- return NDIS_STATUS_RESOURCES;
+ /* Set it to 1 if it fails because some drivers don't support this (?)*/
+ Adapter->NdisMiniportBlock.MaxSendPackets = 1;
}
+ NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->NdisMiniportBlock.CurrentLookahead));
+
return STATUS_SUCCESS;
}
PNDIS_CONFIGURATION_PARAMETER ConfigParam;
NDIS_HANDLE ConfigHandle;
ULONG Size;
-/* FIXME - KIRQL OldIrql; */
+ LARGE_INTEGER Timeout;
+ UINT MaxMulticastAddresses;
+ ULONG BytesWritten;
/*
* Prepare wrapper context used by HW and configuration routines.
if (!NT_SUCCESS(Status))
{
NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key\n"));
+ ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
return Status;
}
* NdisMQueryAdapterResources.
*/
- if (Stack->Parameters.StartDevice.AllocatedResources != NULL &&
- Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)
+ if (Stack->Parameters.StartDevice.AllocatedResources != NULL)
{
ResourceCount = Stack->Parameters.StartDevice.AllocatedResources->List[0].
PartialResourceList.Count;
ExAllocatePool(PagedPool, ResourceListSize);
if (Adapter->NdisMiniportBlock.AllocatedResources == NULL)
{
+ NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
return STATUS_INSUFFICIENT_RESOURCES;
}
- Adapter->NdisMiniportBlock.AllocatedResourcesTranslated =
+ Adapter->NdisMiniportBlock.Resources =
ExAllocatePool(PagedPool, ResourceListSize);
- if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated == NULL)
- {
+ if (!Adapter->NdisMiniportBlock.Resources)
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
- Adapter->NdisMiniportBlock.AllocatedResources = NULL;
- ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
+ ExInterlockedRemoveEntryList(&Adapter->ListEntry, &AdapterListLock);
return STATUS_INSUFFICIENT_RESOURCES;
- }
+ }
+
+ RtlCopyMemory(Adapter->NdisMiniportBlock.Resources,
+ Stack->Parameters.StartDevice.AllocatedResources,
+ ResourceListSize);
RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResources,
Stack->Parameters.StartDevice.AllocatedResources,
ResourceListSize);
+ }
+
+ if (Stack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)
+ {
+ ResourceCount = Stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].
+ PartialResourceList.Count;
+ ResourceListSize =
+ FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
+ PartialDescriptors[ResourceCount]);
+
+ Adapter->NdisMiniportBlock.AllocatedResourcesTranslated =
+ ExAllocatePool(PagedPool, ResourceListSize);
+ if (Adapter->NdisMiniportBlock.AllocatedResourcesTranslated == NULL)
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
+ ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated,
Stack->Parameters.StartDevice.AllocatedResourcesTranslated,
ResourceListSize);
- }
+ }
/*
* Store the Bus Type, Bus Number and Slot information. It's used by
*/
NdisOpenConfiguration(&NdisStatus, &ConfigHandle, (NDIS_HANDLE)&WrapperContext);
+ if (NdisStatus != NDIS_STATUS_SUCCESS)
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("Failed to open configuration key\n"));
+ ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
+ return NdisStatus;
+ }
Size = sizeof(ULONG);
Status = IoGetDeviceProperty(Adapter->NdisMiniportBlock.PhysicalDeviceObject,
Adapter->NdisMiniportBlock.SlotNumber = SlotNumber.u.AsULONG;
}
+ WrapperContext.SlotNumber = Adapter->NdisMiniportBlock.SlotNumber;
+
NdisCloseConfiguration(ConfigHandle);
/* Set handlers (some NDIS macros require these) */
Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
Adapter->NdisMiniportBlock.StatusHandler = MiniStatus;
Adapter->NdisMiniportBlock.StatusCompleteHandler= MiniStatusComplete;
+ Adapter->NdisMiniportBlock.SendPacketsHandler = ProSendPackets;
+ Adapter->NdisMiniportBlock.QueryCompleteHandler = MiniRequestComplete;
+ Adapter->NdisMiniportBlock.SetCompleteHandler = MiniRequestComplete;
/*
* Call MiniportInitialize.
ZwClose(WrapperContext.RegistryHandle);
- if (NdisStatus != NDIS_STATUS_SUCCESS ||
- SelectedMediumIndex >= MEDIA_ARRAY_SIZE)
+ if (NdisStatus != NDIS_STATUS_SUCCESS)
{
NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter.\n"));
ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
- if (NdisStatus == NDIS_STATUS_SUCCESS) NdisStatus = NDIS_STATUS_FAILURE;
- return (NTSTATUS)NdisStatus;
+ return NdisStatus;
+ }
+
+ if (SelectedMediumIndex >= MEDIA_ARRAY_SIZE)
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() selected a bad index\n"));
+ ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
+ return NDIS_STATUS_UNSUPPORTED_MEDIA;
}
Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
NdisStatus = DoQueries(Adapter, AddressOID);
if (NdisStatus == NDIS_STATUS_SUCCESS)
{
- Success = EthCreateFilter(32, /* FIXME: Query this from miniport. */
+ NdisStatus = MiniQueryInformation(Adapter, OID_802_3_MAXIMUM_LIST_SIZE, sizeof(UINT),
+ &MaxMulticastAddresses, &BytesWritten);
+
+ if (NdisStatus != NDIS_STATUS_SUCCESS)
+ {
+ ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
+ NDIS_DbgPrint(MIN_TRACE, ("MiniQueryInformation failed (%x)\n", NdisStatus));
+ return NdisStatus;
+ }
+
+ Success = EthCreateFilter(MaxMulticastAddresses,
Adapter->Address.Type.Medium802_3,
&Adapter->NdisMiniportBlock.EthDB);
if (Success)
/* FIXME: Support other types of media */
NDIS_DbgPrint(MIN_TRACE, ("error: unsupported media\n"));
ASSERT(FALSE);
-/* FIXME - KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); */
ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
return STATUS_UNSUCCESSFUL;
}
- if (!Success || NdisStatus != NDIS_STATUS_SUCCESS)
+ if (NdisStatus != NDIS_STATUS_SUCCESS)
{
- NDIS_DbgPrint(MAX_TRACE, ("couldn't create filter (%x)\n", NdisStatus));
- if (Adapter->LookaheadBuffer)
- {
- ExFreePool(Adapter->LookaheadBuffer);
- Adapter->LookaheadBuffer = NULL;
- }
- ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
- if (NdisStatus == NDIS_STATUS_SUCCESS) NdisStatus = NDIS_STATUS_FAILURE;
- return (NTSTATUS)NdisStatus;
+ NDIS_DbgPrint(MIN_TRACE, ("couldn't create filter (%x)\n", NdisStatus));
+ return NdisStatus;
}
+ /* Check for a hang every two seconds if it wasn't set in MiniportInitialize */
+ if (Adapter->NdisMiniportBlock.CheckForHangSeconds == 0)
+ Adapter->NdisMiniportBlock.CheckForHangSeconds = 2;
+
Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStarted;
+ IoSetDeviceInterfaceState(&Adapter->NdisMiniportBlock.SymbolicLinkName, TRUE);
+
+ Timeout.QuadPart = Int32x32To64(Adapter->NdisMiniportBlock.CheckForHangSeconds, -1000000);
+ KeSetTimerEx(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer, Timeout,
+ Adapter->NdisMiniportBlock.CheckForHangSeconds * 1000,
+ &Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc);
+
/* Put adapter in adapter list for this miniport */
ExInterlockedInsertTailList(&Adapter->NdisMiniportBlock.DriverHandle->DeviceList, &Adapter->MiniportListEntry, &Adapter->NdisMiniportBlock.DriverHandle->Lock);
*/
{
PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
- KIRQL OldIrql;
/* Remove adapter from adapter list for this miniport */
- KeAcquireSpinLock(&Adapter->NdisMiniportBlock.DriverHandle->Lock, &OldIrql);
- RemoveEntryList(&Adapter->MiniportListEntry);
- KeReleaseSpinLock(&Adapter->NdisMiniportBlock.DriverHandle->Lock, OldIrql);
+ ExInterlockedRemoveEntryList(&Adapter->MiniportListEntry, &Adapter->NdisMiniportBlock.DriverHandle->Lock);
/* Remove adapter from global adapter list */
- KeAcquireSpinLock(&AdapterListLock, &OldIrql);
- RemoveEntryList(&Adapter->ListEntry);
- KeReleaseSpinLock(&AdapterListLock, OldIrql);
+ ExInterlockedRemoveEntryList(&Adapter->ListEntry, &AdapterListLock);
+
+ KeCancelTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
(*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.HaltHandler)(Adapter);
- if (Adapter->LookaheadBuffer)
- {
- ExFreePool(Adapter->LookaheadBuffer);
- Adapter->LookaheadBuffer = NULL;
- }
+ IoSetDeviceInterfaceState(&Adapter->NdisMiniportBlock.SymbolicLinkName, FALSE);
+
if (Adapter->NdisMiniportBlock.AllocatedResources)
{
ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
Adapter->NdisMiniportBlock.AllocatedResourcesTranslated = NULL;
}
+ if (Adapter->NdisMiniportBlock.Resources)
+ {
+ ExFreePool(Adapter->NdisMiniportBlock.Resources);
+ Adapter->NdisMiniportBlock.Resources = NULL;
+ }
+
+ if (Adapter->NdisMiniportBlock.EthDB)
+ {
+ EthDeleteFilter(Adapter->NdisMiniportBlock.EthDB);
+ Adapter->NdisMiniportBlock.EthDB = NULL;
+ }
+
Adapter->NdisMiniportBlock.OldPnPDeviceState = Adapter->NdisMiniportBlock.PnPDeviceState;
Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceStopped;
return STATUS_SUCCESS;
}
+NTSTATUS
+NTAPI
+NdisIShutdown(
+ IN PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ PLOGICAL_ADAPTER Adapter = DeviceObject->DeviceExtension;
+ PMINIPORT_BUGCHECK_CONTEXT Context = Adapter->BugcheckContext;
+ ADAPTER_SHUTDOWN_HANDLER ShutdownHandler = Context->ShutdownHandler;
+
+ ASSERT(ShutdownHandler);
+
+ ShutdownHandler(Context->DriverContext);
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NdisIDeviceIoControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ PIRP Irp)
+{
+ PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
+ PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+ NDIS_STATUS Status = STATUS_NOT_SUPPORTED;
+
+ Irp->IoStatus.Information = 0;
+
+ ASSERT(Adapter);
+
+ switch (Stack->Parameters.DeviceIoControl.IoControlCode)
+ {
+ case IOCTL_NDIS_QUERY_GLOBAL_STATS:
+ Status = MiniQueryInformation(Adapter,
+ *(PNDIS_OID)Irp->AssociatedIrp.SystemBuffer,
+ Stack->Parameters.DeviceIoControl.OutputBufferLength,
+ MmGetSystemAddressForMdl(Irp->MdlAddress),
+ &Irp->IoStatus.Information);
+ break;
+
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+
+ if (Status != NDIS_STATUS_PENDING)
+ {
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+ else
+ IoMarkIrpPending(Irp);
+
+ return Status;
+}
+
\f
NTSTATUS
NTAPI
{
Status = NdisIPnPStartDevice(DeviceObject, Irp);
}
+ else
+ NDIS_DbgPrint(MIN_TRACE, ("Lower driver failed device start\n"));
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
{
Status = NdisIPnPStopDevice(DeviceObject, Irp);
}
+ else
+ NDIS_DbgPrint(MIN_TRACE, ("Lower driver failed device stop\n"));
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
- case IRP_MN_QUERY_DEVICE_RELATIONS:
- Status = STATUS_NOT_SUPPORTED;
+ case IRP_MN_QUERY_REMOVE_DEVICE:
+ case IRP_MN_QUERY_STOP_DEVICE:
+ Status = NdisIPnPQueryStopDevice(DeviceObject, Irp);
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
+ case IRP_MN_CANCEL_REMOVE_DEVICE:
+ case IRP_MN_CANCEL_STOP_DEVICE:
+ Status = NdisIPnPCancelStopDevice(DeviceObject, Irp);
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ break;
+
+ case IRP_MN_QUERY_PNP_DEVICE_STATE:
+ Status = NDIS_STATUS_SUCCESS;
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information |= Adapter->NdisMiniportBlock.PnPFlags;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ break;
+
default:
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(Adapter->NdisMiniportBlock.NextDeviceObject, Irp);
PDEVICE_OBJECT DeviceObject;
PLOGICAL_ADAPTER Adapter;
NTSTATUS Status;
+ UINT i;
/*
* Gain the access to the miniport data structure first.
*/
- MiniportPtr = IoGetDriverObjectExtension(DriverObject, (PVOID)TAG('D','I','M','N'));
+ MiniportPtr = IoGetDriverObjectExtension(DriverObject, (PVOID)'NMID');
if (MiniportPtr == NULL)
{
- NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get driver object extension.\n"));
- return STATUS_UNSUCCESSFUL;
+ NDIS_DbgPrint(MIN_TRACE, ("Can't get driver object extension.\n"));
+ return NDIS_STATUS_FAILURE;
}
Miniport = *MiniportPtr;
Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
0, NULL, &DriverKeyLength);
- if (Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW)
+ if (Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_SUCCESS)
{
- NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key length.\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport driver key length.\n"));
return Status;
}
sizeof(ClassKeyName) + sizeof(LinkageKeyName));
if (LinkageKeyBuffer == NULL)
{
- NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate memory for driver key name.\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("Can't allocate memory for driver key name.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
&DriverKeyLength);
if (!NT_SUCCESS(Status))
{
- NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport driver key.\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport driver key.\n"));
ExFreePool(LinkageKeyBuffer);
return Status;
}
ExFreePool(LinkageKeyBuffer);
if (!NT_SUCCESS(Status))
{
- NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't get miniport device name. (%x)\n", Status));
+ NDIS_DbgPrint(MIN_TRACE, ("Can't get miniport device name. (%x)\n", Status));
return Status;
}
Adapter = (PLOGICAL_ADAPTER)DeviceObject->DeviceExtension;
KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock);
InitializeListHead(&Adapter->ProtocolListHead);
- Adapter->NdisMiniportBlock.DriverHandle = Miniport;
- Adapter->NdisMiniportBlock.MiniportName = ExportName;
+ Status = IoRegisterDeviceInterface(PhysicalDeviceObject,
+ &GUID_DEVINTERFACE_NET,
+ NULL,
+ &Adapter->NdisMiniportBlock.SymbolicLinkName);
+
+ if (!NT_SUCCESS(Status))
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("Could not create device interface.\n"));
+ IoDeleteDevice(DeviceObject);
+ RtlFreeUnicodeString(&ExportName);
+ return Status;
+ }
+ Adapter->NdisMiniportBlock.DriverHandle = Miniport;
+ Adapter->NdisMiniportBlock.MiniportName = ExportName;
Adapter->NdisMiniportBlock.DeviceObject = DeviceObject;
Adapter->NdisMiniportBlock.PhysicalDeviceObject = PhysicalDeviceObject;
Adapter->NdisMiniportBlock.NextDeviceObject =
Adapter->NdisMiniportBlock.OldPnPDeviceState = 0;
Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceAdded;
- KeInitializeDpc(&Adapter->NdisMiniportBlock.DeferredDpc, MiniportDpc, (PVOID)Adapter);
+ for (i = 0; i < NUMBER_OF_WORK_ITEM_TYPES; i++)
+ Adapter->NdisMiniportBlock.WorkQueue[i].Next = NULL;
+
+ KeInitializeTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
+ KeInitializeDpc(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc, MiniportHangDpc, Adapter);
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
break;
default:
- NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics version.\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics version.\n"));
return NDIS_STATUS_BAD_VERSION;
}
+ NDIS_DbgPrint(MIN_TRACE, ("Initializing an NDIS %u.%u miniport\n",
+ MiniportCharacteristics->MajorNdisVersion,
+ MiniportCharacteristics->MinorNdisVersion));
+
if (CharacteristicsLength < MinSize)
{
- NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics length.\n"));
return NDIS_STATUS_BAD_CHARACTERISTICS;
}
/* Check if mandatory MiniportXxx functions are specified */
if ((!MiniportCharacteristics->HaltHandler) ||
- (!MiniportCharacteristics->InitializeHandler)||
- (!MiniportCharacteristics->QueryInformationHandler) ||
- (!MiniportCharacteristics->ResetHandler) ||
- (!MiniportCharacteristics->SetInformationHandler))
+ (!MiniportCharacteristics->InitializeHandler)||
+ (!MiniportCharacteristics->ResetHandler))
{
- NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics.\n"));
return NDIS_STATUS_BAD_CHARACTERISTICS;
}
+ if (MiniportCharacteristics->MajorNdisVersion < 0x05)
+ {
+ if ((!MiniportCharacteristics->QueryInformationHandler) ||
+ (!MiniportCharacteristics->SetInformationHandler))
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (Set/Query)\n"));
+ return NDIS_STATUS_BAD_CHARACTERISTICS;
+ }
+ }
+ else
+ {
+ if (((!MiniportCharacteristics->QueryInformationHandler) ||
+ (!MiniportCharacteristics->SetInformationHandler)) &&
+ (!MiniportCharacteristics->CoRequestHandler))
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (Set/Query)\n"));
+ return NDIS_STATUS_BAD_CHARACTERISTICS;
+ }
+ }
+
if (MiniportCharacteristics->MajorNdisVersion == 0x03)
{
if (!MiniportCharacteristics->SendHandler)
{
- NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 3.0)\n"));
return NDIS_STATUS_BAD_CHARACTERISTICS;
}
}
- else if (MiniportCharacteristics->MajorNdisVersion >= 0x04)
+ else if (MiniportCharacteristics->MajorNdisVersion == 0x04)
{
- /* NDIS 4.0+ */
+ /* NDIS 4.0 */
if ((!MiniportCharacteristics->SendHandler) &&
(!MiniportCharacteristics->SendPacketsHandler))
{
- NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 4.0)\n"));
+ return NDIS_STATUS_BAD_CHARACTERISTICS;
+ }
+ }
+ else if (MiniportCharacteristics->MajorNdisVersion == 0x05)
+ {
+ /* TODO: Add more checks here */
+
+ if ((!MiniportCharacteristics->SendHandler) &&
+ (!MiniportCharacteristics->SendPacketsHandler) &&
+ (!MiniportCharacteristics->CoSendPacketsHandler))
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("Bad miniport characteristics. (NDIS 5.0)\n"));
return NDIS_STATUS_BAD_CHARACTERISTICS;
}
}
* structure in the driver extension or what?
*/
- Status = IoAllocateDriverObjectExtension(Miniport->DriverObject, (PVOID)TAG('D','I','M','N'),
+ Status = IoAllocateDriverObjectExtension(Miniport->DriverObject, (PVOID)'NMID',
sizeof(PNDIS_M_DRIVER_BLOCK), (PVOID*)&MiniportPtr);
if (!NT_SUCCESS(Status))
{
- NDIS_DbgPrint(DEBUG_MINIPORT, ("Can't allocate driver object extension.\n"));
+ NDIS_DbgPrint(MIN_TRACE, ("Can't allocate driver object extension.\n"));
return NDIS_STATUS_RESOURCES;
}
*MiniportPtr = Miniport;
Miniport->DriverObject->MajorFunction[IRP_MJ_PNP] = NdisIDispatchPnp;
+ Miniport->DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = NdisIShutdown;
+ Miniport->DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NdisIDeviceIoControl;
Miniport->DriverObject->DriverExtension->AddDevice = NdisIAddDevice;
return NDIS_STATUS_SUCCESS;
}
\f
-/*
- * @implemented
- */
-#undef NdisMSetInformationComplete
-VOID
-EXPORT
-NdisMSetInformationComplete(
- IN NDIS_HANDLE MiniportAdapterHandle,
- IN NDIS_STATUS Status)
-{
- (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->SetCompleteHandler)(MiniportAdapterHandle, Status);
-}
-
-\f
/*
* @implemented
*/
* AdapterType = Specifies the I/O bus interface of the caller's NIC
*/
{
- /* TODO: Take CheckForHandTimeInSeconds into account! */
-
PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext;
Adapter->NdisMiniportBlock.Flags = AttributeFlags;
Adapter->NdisMiniportBlock.AdapterType = AdapterType;
+ if (CheckForHangTimeInSeconds > 0)
+ Adapter->NdisMiniportBlock.CheckForHangSeconds = CheckForHangTimeInSeconds;
if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
NDIS_DbgPrint(MAX_TRACE, ("Intermediate drivers not supported yet.\n"));
+
+
+ if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.AdapterShutdownHandler)
+ {
+ NDIS_DbgPrint(MAX_TRACE, ("Miniport set AdapterShutdownHandler in MiniportCharacteristics\n"));
+ NdisMRegisterAdapterShutdownHandler(Adapter,
+ Adapter->NdisMiniportBlock.MiniportAdapterContext,
+ Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.AdapterShutdownHandler);
+ }
}
\f
ExFreePool(Miniport->RegistryPath->Buffer);
ExFreePool(Miniport->RegistryPath);
+ ExInterlockedRemoveEntryList(&Miniport->ListEntry, &MiniportListLock);
ExFreePool(Miniport);
}
+
+/*
+ * @implemented
+ */
+NDIS_STATUS
+EXPORT
+NdisMQueryAdapterInstanceName(
+ OUT PNDIS_STRING AdapterInstanceName,
+ IN NDIS_HANDLE MiniportAdapterHandle)
+/*
+ * FUNCTION:
+ * ARGUMENTS:
+ * NOTES:
+ * NDIS 5.0
+ */
+{
+ PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
+ UNICODE_STRING AdapterName;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ AdapterName.Length = 0;
+ AdapterName.MaximumLength = Adapter->NdisMiniportBlock.MiniportName.MaximumLength;
+ AdapterName.Buffer = ExAllocatePool(PagedPool, AdapterName.MaximumLength);
+ if (!AdapterName.Buffer) {
+ NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ RtlCopyUnicodeString(&AdapterName, &Adapter->NdisMiniportBlock.MiniportName);
+
+ *AdapterInstanceName = AdapterName;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
+VOID
+EXPORT
+NdisDeregisterAdapterShutdownHandler(
+ IN NDIS_HANDLE NdisAdapterHandle)
+/*
+ * FUNCTION:
+ * ARGUMENTS:
+ * NOTES:
+ * NDIS 4.0
+ */
+{
+ NdisMDeregisterAdapterShutdownHandler(NdisAdapterHandle);
+}
+
+
+/*
+ * @implemented
+ */
+VOID
+EXPORT
+NdisRegisterAdapterShutdownHandler(
+ IN NDIS_HANDLE NdisAdapterHandle,
+ IN PVOID ShutdownContext,
+ IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
+/*
+ * FUNCTION:
+ * ARGUMENTS:
+ * NOTES:
+ * NDIS 4.0
+ */
+{
+ NdisMRegisterAdapterShutdownHandler(NdisAdapterHandle,
+ ShutdownContext,
+ ShutdownHandler);
+}
+
+/*
+ * @implemented
+ */
+VOID
+EXPORT
+NdisMGetDeviceProperty(
+ IN NDIS_HANDLE MiniportAdapterHandle,
+ IN OUT PDEVICE_OBJECT *PhysicalDeviceObject OPTIONAL,
+ IN OUT PDEVICE_OBJECT *FunctionalDeviceObject OPTIONAL,
+ IN OUT PDEVICE_OBJECT *NextDeviceObject OPTIONAL,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources OPTIONAL,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResourcesTranslated OPTIONAL)
+/*
+ * FUNCTION:
+ * ARGUMENTS:
+ * NOTES:
+ * NDIS 5.0
+ */
+{
+ PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
+
+ if (PhysicalDeviceObject != NULL)
+ *PhysicalDeviceObject = Adapter->NdisMiniportBlock.PhysicalDeviceObject;
+
+ if (FunctionalDeviceObject != NULL)
+ *FunctionalDeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
+
+ if (NextDeviceObject != NULL)
+ *NextDeviceObject = Adapter->NdisMiniportBlock.NextDeviceObject;
+
+ if (AllocatedResources != NULL)
+ *AllocatedResources = Adapter->NdisMiniportBlock.AllocatedResources;
+
+ if (AllocatedResourcesTranslated != NULL)
+ *AllocatedResourcesTranslated = Adapter->NdisMiniportBlock.AllocatedResourcesTranslated;
+}
+
+/*
+ * @implemented
+ */
+VOID
+EXPORT
+NdisMRegisterUnloadHandler(
+ IN NDIS_HANDLE NdisWrapperHandle,
+ IN PDRIVER_UNLOAD UnloadHandler)
+/*
+ * FUNCTION:
+ * ARGUMENTS:
+ * NOTES:
+ * NDIS 5.0
+ */
+{
+ PNDIS_M_DRIVER_BLOCK DriverBlock = NdisWrapperHandle;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Miniport registered unload handler\n"));
+
+ DriverBlock->DriverObject->DriverUnload = UnloadHandler;
+}
+
+/*
+ * @implemented
+ */
+NDIS_STATUS
+EXPORT
+NdisMRegisterDevice(
+ IN NDIS_HANDLE NdisWrapperHandle,
+ IN PNDIS_STRING DeviceName,
+ IN PNDIS_STRING SymbolicName,
+ IN PDRIVER_DISPATCH MajorFunctions[],
+ OUT PDEVICE_OBJECT *pDeviceObject,
+ OUT NDIS_HANDLE *NdisDeviceHandle)
+/*
+ * FUNCTION:
+ * ARGUMENTS:
+ * NOTES:
+ * NDIS 5.0
+ */
+{
+ PNDIS_M_DRIVER_BLOCK DriverBlock = NdisWrapperHandle;
+ PNDIS_M_DEVICE_BLOCK DeviceBlock;
+ PDEVICE_OBJECT DeviceObject;
+ NDIS_STATUS Status;
+ UINT i;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
+
+ Status = IoCreateDevice(DriverBlock->DriverObject,
+ 0, /* This space is reserved for us. Should we use it? */
+ DeviceName,
+ FILE_DEVICE_NETWORK,
+ 0,
+ FALSE,
+ &DeviceObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("IoCreateDevice failed (%x)\n", Status));
+ return Status;
+ }
+
+ Status = IoCreateSymbolicLink(SymbolicName, DeviceName);
+
+ if (!NT_SUCCESS(Status))
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("IoCreateSymbolicLink failed (%x)\n", Status));
+ IoDeleteDevice(DeviceObject);
+ return Status;
+ }
+
+ DeviceBlock = ExAllocatePool(NonPagedPool, sizeof(NDIS_M_DEVICE_BLOCK));
+
+ if (!DeviceBlock)
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
+ IoDeleteDevice(DeviceObject);
+ IoDeleteSymbolicLink(SymbolicName);
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
+ DriverBlock->DriverObject->MajorFunction[i] = MajorFunctions[i];
+
+ DriverBlock->DriverObject->MajorFunction[IRP_MJ_PNP] = NdisIDispatchPnp;
+
+ DeviceBlock->DeviceObject = DeviceObject;
+ DeviceBlock->SymbolicName = SymbolicName;
+
+ *pDeviceObject = DeviceObject;
+ *NdisDeviceHandle = DeviceBlock;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
+NDIS_STATUS
+EXPORT
+NdisMDeregisterDevice(
+ IN NDIS_HANDLE NdisDeviceHandle)
+/*
+ * FUNCTION:
+ * ARGUMENTS:
+ * NOTES:
+ * NDIS 5.0
+ */
+{
+ PNDIS_M_DEVICE_BLOCK DeviceBlock = NdisDeviceHandle;
+
+ IoDeleteDevice(DeviceBlock->DeviceObject);
+
+ IoDeleteSymbolicLink(DeviceBlock->SymbolicName);
+
+ ExFreePool(DeviceBlock);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
+NDIS_STATUS
+EXPORT
+NdisQueryAdapterInstanceName(
+ OUT PNDIS_STRING AdapterInstanceName,
+ IN NDIS_HANDLE NdisBindingHandle)
+/*
+ * FUNCTION:
+ * ARGUMENTS:
+ * NOTES:
+ * NDIS 5.0
+ */
+{
+ PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
+ PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
+
+ return NdisMQueryAdapterInstanceName(AdapterInstanceName,
+ Adapter);
+}
+
+/*
+ * @implemented
+ */
+VOID
+EXPORT
+NdisCompletePnPEvent(
+ IN NDIS_STATUS Status,
+ IN NDIS_HANDLE NdisBindingHandle,
+ IN PNET_PNP_EVENT NetPnPEvent)
+/*
+ * FUNCTION:
+ * ARGUMENTS:
+ * NOTES:
+ * NDIS 5.0
+ */
+{
+ PIRP Irp = (PIRP)NetPnPEvent->NdisReserved[0];
+ PLIST_ENTRY CurrentEntry = (PLIST_ENTRY)NetPnPEvent->NdisReserved[1];
+ PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
+ PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
+ NDIS_STATUS NdisStatus;
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);
+ ExFreePool(NetPnPEvent);
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return;
+ }
+
+ while (CurrentEntry != &Adapter->ProtocolListHead)
+ {
+ AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
+
+ NdisStatus = (*AdapterBinding->ProtocolBinding->Chars.PnPEventHandler)(
+ AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
+ NetPnPEvent);
+
+ if (NdisStatus == NDIS_STATUS_PENDING)
+ {
+ NetPnPEvent->NdisReserved[1] = (ULONG_PTR)CurrentEntry->Flink;
+ return;
+ }
+ else if (NdisStatus != NDIS_STATUS_SUCCESS)
+ {
+ if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);
+ ExFreePool(NetPnPEvent);
+ Irp->IoStatus.Status = NdisStatus;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return;
+ }
+
+ CurrentEntry = CurrentEntry->Flink;
+ }
+
+ if (NetPnPEvent->Buffer) ExFreePool(NetPnPEvent->Buffer);
+ ExFreePool(NetPnPEvent);
+
+ Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+}
+
+/*
+ * @implemented
+ */
+VOID
+EXPORT
+NdisCancelSendPackets(
+ IN NDIS_HANDLE NdisBindingHandle,
+ IN PVOID CancelId)
+{
+ PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
+ PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called for ID %x.\n", CancelId));
+
+ if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CancelSendPacketsHandler)
+ {
+ (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CancelSendPacketsHandler)(
+ Adapter->NdisMiniportBlock.MiniportAdapterContext,
+ CancelId);
+ }
+}
+
+
+/*
+ * @implemented
+ */
+NDIS_HANDLE
+EXPORT
+NdisIMGetBindingContext(
+ IN NDIS_HANDLE NdisBindingHandle)
+/*
+ * FUNCTION:
+ * ARGUMENTS:
+ * NOTES:
+ * NDIS 5.0
+ */
+{
+ PADAPTER_BINDING AdapterBinding = NdisBindingHandle;
+ PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ return Adapter->NdisMiniportBlock.DeviceContext;
+}
+
+
+/*
+ * @implemented
+ */
+NDIS_HANDLE
+EXPORT
+NdisIMGetDeviceContext(
+ IN NDIS_HANDLE MiniportAdapterHandle)
+/*
+ * FUNCTION:
+ * ARGUMENTS:
+ * NOTES:
+ * NDIS 5.0
+ */
+{
+ PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ return Adapter->NdisMiniportBlock.DeviceContext;
+}
+
/* EOF */