* PacketSize = Total size of received packet
*/
{
- /* KIRQL OldIrql; */
+ KIRQL OldIrql;
PLIST_ENTRY CurrentEntry;
PADAPTER_BINDING AdapterBinding;
MiniDisplayPacket2(HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize);
- /*
- * XXX Think about this. This is probably broken. Spinlocks are
- * taken out for now until i comprehend the Right Way to do this.
- *
- * This used to acquire the MiniportBlock spinlock and hold it until
- * just before the call to ReceiveHandler. It would then release and
- * subsequently re-acquire the lock.
- *
- * I don't see how this does any good, as it would seem he's just
- * trying to protect the packet list. If somebody else dequeues
- * a packet, we are in fact in bad shape, but we don't want to
- * necessarily call the receive handler at elevated irql either.
- *
- * therefore: We *are* going to call the receive handler at high irql
- * (due to holding the lock) for now, and eventually we have to
- * figure out another way to protect this packet list.
- *
- * UPDATE: this is busted; this results in a recursive lock acquisition.
- */
- //NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
- //KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+ NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
{
CurrentEntry = Adapter->ProtocolListHead.Flink;
NDIS_DbgPrint(DEBUG_MINIPORT, ("CurrentEntry = %x\n", CurrentEntry));
AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterBinding = %x\n", AdapterBinding));
- /* see above */
- /* 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);
- /* see above */
- /* KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); */
-
CurrentEntry = CurrentEntry->Flink;
}
}
- //KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
}
\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;
-
-#define PACKET_TAG (('k' << 24) + ('P' << 16) + ('D' << 8) + 'N')
-
- NdisAllocateMemoryWithTag((PVOID)&PacketBuffer, 1518, PACKET_TAG);
- if(!PacketBuffer)
- {
- NDIS_DbgPrint(MIN_TRACE, ("insufficient resources\n"));
- return;
- }
-
- NdisQueryPacket(PacketArray[i], NULL, NULL, &NdisBuffer, NULL);
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
- while(NdisBuffer)
- {
- PNDIS_BUFFER CurrentBuffer;
- PVOID BufferVa;
- UINT BufferLen;
+ CurrentEntry = Adapter->ProtocolListHead.Flink;
- NdisQueryBuffer(NdisBuffer, &BufferVa, &BufferLen);
- memcpy(PacketBuffer + PacketLength, BufferVa, BufferLen);
- PacketLength += BufferLen;
+ while (CurrentEntry != &Adapter->ProtocolListHead)
+ {
+ AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
- CurrentBuffer = NdisBuffer;
- NdisGetNextBuffer(CurrentBuffer, &NdisBuffer);
- }
-
- NDIS_DbgPrint(MID_TRACE, ("indicating a %d-byte packet\n", PacketLength));
+ if (AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler)
+ {
+ for (i = 0; i < NumberOfPackets; i++)
+ {
+ (*AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler)(
+ AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
+ PacketArray[i]);
+ }
+ }
- 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;
+ KIRQL OldIrql;
+ NDIS_DbgPrint(MIN_TRACE, ("FIXME: MiniResetComplete is partially implemented\n"));
+ NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+ Adapter->MiniportBusy = FALSE;
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
}
\f
VOID NTAPI
MiniRequestComplete(
- IN PNDIS_MINIPORT_BLOCK Adapter,
+ IN PNDIS_HANDLE MiniportAdapterHandle,
IN PNDIS_REQUEST Request,
IN NDIS_STATUS Status)
{
+ PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
PNDIS_REQUEST_MAC_BLOCK MacBlock = (PNDIS_REQUEST_MAC_BLOCK)Request->MacReserved;
+ KIRQL OldIrql;
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
if( MacBlock->Binding->RequestCompleteHandler ) {
(*MacBlock->Binding->RequestCompleteHandler)(
MacBlock->Binding->ProtocolBindingContext,
Request,
Status);
}
+ KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+ Adapter->MiniportBusy = FALSE;
+ KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+ KeLowerIrql(OldIrql);
}
VOID NTAPI
* Status = Status of send operation
*/
{
+ PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
PADAPTER_BINDING AdapterBinding;
+ KIRQL OldIrql;
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
(*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
Packet,
Status);
+ KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+ Adapter->MiniportBusy = FALSE;
+ KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+ KeLowerIrql(OldIrql);
}
IN NDIS_STATUS Status,
IN UINT BytesTransferred)
{
+ PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
PADAPTER_BINDING AdapterBinding;
+ KIRQL OldIrql;
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0];
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
(*AdapterBinding->ProtocolBinding->Chars.SendCompleteHandler)(
AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
Packet,
Status);
+ KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+ Adapter->MiniportBusy = FALSE;
+ KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+ KeLowerIrql(OldIrql);
}
\f
KeAcquireSpinLock(&AdapterListLock, &OldIrql);
{
CurrentEntry = AdapterListHead.Flink;
-
+
while (CurrentEntry != &AdapterListHead)
{
Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry);
NDIS_DbgPrint(DEBUG_MINIPORT, ("Examining adapter 0x%lx\n", Adapter));
NDIS_DbgPrint(DEBUG_MINIPORT, ("AdapterName = %wZ\n", AdapterName));
NDIS_DbgPrint(DEBUG_MINIPORT, ("DeviceName = %wZ\n", &Adapter->NdisMiniportBlock.MiniportName));
-
+
if (RtlCompareUnicodeString(AdapterName, &Adapter->NdisMiniportBlock.MiniportName, TRUE) == 0)
{
break;
}
-
+
Adapter = NULL;
CurrentEntry = CurrentEntry->Flink;
}
{
NDIS_STATUS NdisStatus;
ULONG BytesNeeded;
+ KIRQL OldIrql;
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
/* call the miniport's queryinfo handler */
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
Adapter->NdisMiniportBlock.MiniportAdapterContext,
Oid,
Size,
BytesWritten,
&BytesNeeded);
+ KeLowerIrql(OldIrql);
/* FIXME: Wait in pending case! */
- /* XXX is status_pending part of success macro? */
- if ((NT_SUCCESS(NdisStatus)) || (NdisStatus == NDIS_STATUS_PENDING))
- {
- NDIS_DbgPrint(DEBUG_MINIPORT, ("Miniport returned status (0x%X).\n", NdisStatus));
- return NdisStatus;
- }
-
return NdisStatus;
}
+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;
+ KIRQL OldIrql;
+
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+ if (Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)
+ Ret = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.CheckForHangHandler)(
+ Adapter->NdisMiniportBlock.MiniportAdapterContext);
+ KeLowerIrql(OldIrql);
+
+ return Ret;
+}
+
+NDIS_STATUS
+MiniReset(
+ PLOGICAL_ADAPTER Adapter,
+ PBOOLEAN AddressingReset)
+/*
+ * FUNCTION: Resets the miniport
+ * ARGUMENTS:
+ * Adapter = Pointer to the logical adapter object
+ * AddressingReset = Set to TRUE if we need to call MiniportSetInformation later
+ * RETURNS:
+ * Status of the operation
+ */
+{
+ NDIS_STATUS Status;
+ KIRQL OldIrql;
+
+ if (Adapter->MiniportBusy) {
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+ MiniQueueWorkItem(Adapter, NdisWorkItemResetRequested, NULL);
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+ return NDIS_STATUS_PENDING;
+ }
+
+ NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_START, NULL, 0);
+ NdisMIndicateStatusComplete(Adapter);
+
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+ Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
+ Adapter->NdisMiniportBlock.MiniportAdapterContext,
+ AddressingReset);
+ KeLowerIrql(OldIrql);
+
+ if (Status != NDIS_STATUS_PENDING) {
+ NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_END, NULL, 0);
+ NdisMIndicateStatusComplete(Adapter);
+ } else {
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+ Adapter->MiniportBusy = TRUE;
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+ }
+
+ return Status;
+}
+
+VOID STDCALL
+MiniportHangDpc(
+ PKDPC Dpc,
+ PVOID DeferredContext,
+ PVOID SystemArgument1,
+ PVOID SystemArgument2)
+{
+ PLOGICAL_ADAPTER Adapter = DeferredContext;
+ BOOLEAN AddressingReset = FALSE;
+
+
+ if (MiniCheckForHang(Adapter)) {
+ NDIS_DbgPrint(MIN_TRACE, ("Miniport detected adapter hang\n"));
+ MiniReset(Adapter, &AddressingReset);
+ }
+
+ /* FIXME: We should call MiniportSetInformation if AddressingReset is TRUE */
+}
+
\f
NDIS_STATUS
FASTCALL
* Status of operation
*/
{
- PNDIS_MINIPORT_WORK_ITEM Item;
+ PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
+ PNDIS_WORK_ITEM NdisWorkItem;
+ PWORK_QUEUE_ITEM WorkQueueItem;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-
+
ASSERT(Adapter);
ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
-
- Item = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
- if (Item == NULL)
+
+ MiniportWorkItem = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
+ if (!MiniportWorkItem)
{
NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return NDIS_STATUS_RESOURCES;
}
-
- Item->WorkItemType = WorkItemType;
- Item->WorkItemContext = WorkItemContext;
-
+
+ NdisWorkItem = ExAllocatePool(NonPagedPool, sizeof(NDIS_WORK_ITEM));
+ if (!NdisWorkItem)
+ {
+ ExFreePool(MiniportWorkItem);
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ MiniportWorkItem->WorkItemType = WorkItemType;
+ MiniportWorkItem->WorkItemContext = WorkItemContext;
+
/* safe due to adapter lock held */
- Item->Link.Next = NULL;
+ MiniportWorkItem->Link.Next = NULL;
if (!Adapter->WorkQueueHead)
{
- Adapter->WorkQueueHead = Item;
- Adapter->WorkQueueTail = Item;
+ Adapter->WorkQueueHead = MiniportWorkItem;
+ Adapter->WorkQueueTail = MiniportWorkItem;
}
else
{
- Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item;
- Adapter->WorkQueueTail = Item;
+ Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)MiniportWorkItem;
+ Adapter->WorkQueueTail = MiniportWorkItem;
}
-
- KeInsertQueueDpc(&Adapter->NdisMiniportBlock.DeferredDpc, NULL, NULL);
-
+
+ WorkQueueItem = (PWORK_QUEUE_ITEM)NdisWorkItem->WrapperReserved;
+
+ NdisWorkItem->Context = Adapter;
+
+ ExInitializeWorkItem(WorkQueueItem, MiniportWorker, NdisWorkItem);
+
+ ExQueueWorkItem(WorkQueueItem, CriticalWorkQueue);
+
return NDIS_STATUS_SUCCESS;
}
* Status of operation
*/
{
- PNDIS_MINIPORT_WORK_ITEM Item;
-
+ PNDIS_MINIPORT_WORK_ITEM MiniportWorkItem;
+ PNDIS_WORK_ITEM NdisWorkItem;
+ PWORK_QUEUE_ITEM WorkQueueItem;
+
+
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-
- Item = Adapter->WorkQueueHead;
-
- if (Item)
+
+ if (Adapter->MiniportBusy) {
+ NDIS_DbgPrint(MID_TRACE, ("Waiting for miniport to become free.\n"));
+ NdisWorkItem = ExAllocatePool(NonPagedPool, sizeof(NDIS_WORK_ITEM));
+ if (!NdisWorkItem) return NDIS_STATUS_RESOURCES;
+ WorkQueueItem = (PWORK_QUEUE_ITEM)NdisWorkItem->WrapperReserved;
+ NdisWorkItem->Context = Adapter;
+ ExInitializeWorkItem(WorkQueueItem, MiniportWorker, NdisWorkItem);
+ ExQueueWorkItem(WorkQueueItem, CriticalWorkQueue);
+ return NDIS_STATUS_FAILURE;
+ }
+
+ MiniportWorkItem = Adapter->WorkQueueHead;
+
+ if (MiniportWorkItem)
{
/* safe due to adapter lock held */
- Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)Item->Link.Next;
-
- if (Item == Adapter->WorkQueueTail)
+ Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)MiniportWorkItem->Link.Next;
+
+ if (MiniportWorkItem == Adapter->WorkQueueTail)
Adapter->WorkQueueTail = NULL;
-
- *WorkItemType = Item->WorkItemType;
- *WorkItemContext = Item->WorkItemContext;
-
- ExFreePool(Item);
-
+
+ *WorkItemType = MiniportWorkItem->WorkItemType;
+ *WorkItemContext = MiniportWorkItem->WorkItemContext;
+
+ ExFreePool(MiniportWorkItem);
+
+ Adapter->MiniportBusy = TRUE;
+
return NDIS_STATUS_SUCCESS;
}
-
+
return NDIS_STATUS_FAILURE;
}
\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;
-
+
+ Adapter->NdisMiniportBlock.MediaRequest = NdisRequest;
+
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
switch (NdisRequest->RequestType)
{
case NdisRequestQueryInformation:
- return (*Adapter->DriverHandle->MiniportCharacteristics.QueryInformationHandler)(
- Adapter->MiniportAdapterContext,
+ 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,
+ 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;
+ Status = NDIS_STATUS_FAILURE;
}
+
+ if (Status == NDIS_STATUS_PENDING) {
+ KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+ Adapter->MiniportBusy = TRUE;
+ KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+ }
+
+ KeLowerIrql(OldIrql);
+ return Status;
}
\f
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;
+ KIRQL OldIrql;
+ ASSERT(Adapter);
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+ if( Adapter->NdisMiniportBlock.QueryCompleteHandler )
+ (Adapter->NdisMiniportBlock.QueryCompleteHandler)(MiniportAdapterHandle, Status);
+ KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+ Adapter->MiniportBusy = FALSE;
+ KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+ KeLowerIrql(OldIrql);
}
-\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
- */
+VOID NTAPI MiniportWorker(IN PVOID WorkItem)
{
+ PNDIS_WORK_ITEM NdisWorkItem = WorkItem;
+ PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(NdisWorkItem->Context);
+ KIRQL OldIrql, RaiseOldIrql;
NDIS_STATUS NdisStatus;
PVOID WorkItemContext;
NDIS_WORK_ITEM_TYPE WorkItemType;
- PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext);
+ BOOLEAN AddressingReset;
- NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
- NdisStatus =
+ NdisStatus =
MiniDequeueWorkItem
(Adapter, &WorkItemType, &WorkItemContext);
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+
if (NdisStatus == NDIS_STATUS_SUCCESS)
{
switch (WorkItemType)
#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_GET_PACKET_STATUS((PNDIS_PACKET)WorkItemContext);
+ }
+ 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 ) {
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+ MiniQueueWorkItem(Adapter, WorkItemType, WorkItemContext);
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+ 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, 0);
+ 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, 0);
+ NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
+ KeLowerIrql(RaiseOldIrql);
+ if( NdisStatus == NDIS_STATUS_RESOURCES ) {
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+ MiniQueueWorkItem(Adapter, WorkItemType, WorkItemContext);
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+ break;
+ }
+ }
}
+
if( NdisStatus != NDIS_STATUS_PENDING ) {
NdisMSendComplete
( 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 )
+ MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
break;
case NdisWorkItemReturnPackets:
break;
case NdisWorkItemResetRequested:
+ NdisMIndicateStatus(Adapter, NDIS_STATUS_RESET_START, NULL, 0);
+ NdisMIndicateStatusComplete(Adapter);
+
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+ NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ResetHandler)(
+ Adapter->NdisMiniportBlock.MiniportAdapterContext,
+ &AddressingReset);
+ KeLowerIrql(OldIrql);
+
+ if (NdisStatus == NDIS_STATUS_PENDING)
+ break;
+
+ 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 );
+ MiniRequestComplete( (NDIS_HANDLE)Adapter, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
break;
case NdisRequestSetInformation:
NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
- MiniRequestComplete( &Adapter->NdisMiniportBlock, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
+ MiniRequestComplete( (NDIS_HANDLE)Adapter, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
break;
default:
break;
}
}
+
+ if( NdisStatus != NDIS_STATUS_PENDING ) {
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+ Adapter->MiniportBusy = FALSE;
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+ }
+
+ ExFreePool(WorkItem);
}
+
\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
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
*/
#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
RegistryPath = ExAllocatePool(PagedPool, sizeof(UNICODE_STRING));
if(!RegistryPath)
{
+ ExFreePool(Miniport);
NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return;
}
if(!RegistryBuffer)
{
NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+ ExFreePool(Miniport);
+ ExFreePool(RegistryPath);
return;
}
* 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");
+
+ IoRegisterShutdownNotification(Adapter->NdisMiniportBlock.DeviceObject);
}
\f
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
/* Get MAC options for adapter */
- NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAC_OPTIONS, sizeof(UINT),
+ NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAC_OPTIONS, sizeof(UINT),
&Adapter->NdisMiniportBlock.MacOptions,
&BytesWritten);
return NdisStatus;
}
+ NdisStatus = MiniQueryInformation(Adapter, OID_GEN_MAXIMUM_SEND_PACKETS, sizeof(ULONG),
+ &Adapter->NdisMiniportBlock.MaxSendPackets, &BytesWritten);
+
+ if (NdisStatus != NDIS_STATUS_SUCCESS)
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_SEND_PACKETS failed. NdisStatus (0x%X).\n", NdisStatus));
+
+ /* 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));
if (Adapter->NdisMiniportBlock.MaximumLookahead != 0)
PNDIS_CONFIGURATION_PARAMETER ConfigParam;
NDIS_HANDLE ConfigHandle;
ULONG Size;
-/* FIXME - KIRQL OldIrql; */
+ LARGE_INTEGER Timeout;
+ /* FIXME - KIRQL OldIrql; */
/*
* 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;
return STATUS_INSUFFICIENT_RESOURCES;
}
+ 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)
{
- ExFreePool(Adapter->NdisMiniportBlock.AllocatedResources);
- Adapter->NdisMiniportBlock.AllocatedResources = NULL;
ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
return STATUS_INSUFFICIENT_RESOURCES;
}
- RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResources,
- Stack->Parameters.StartDevice.AllocatedResources,
- ResourceListSize);
-
RtlCopyMemory(Adapter->NdisMiniportBlock.AllocatedResourcesTranslated,
Stack->Parameters.StartDevice.AllocatedResourcesTranslated,
ResourceListSize);
- }
+ }
/*
* Store the Bus Type, Bus Number and Slot information. It's used by
}
NdisCloseConfiguration(ConfigHandle);
+ /* Set handlers (some NDIS macros require these) */
+ Adapter->NdisMiniportBlock.EthRxCompleteHandler = EthFilterDprIndicateReceiveComplete;
+ Adapter->NdisMiniportBlock.EthRxIndicateHandler = EthFilterDprIndicateReceive;
+ Adapter->NdisMiniportBlock.SendCompleteHandler = MiniSendComplete;
+ Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
+ Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
+ Adapter->NdisMiniportBlock.TDCompleteHandler = MiniTransferDataComplete;
+ Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
+ Adapter->NdisMiniportBlock.StatusHandler = MiniStatus;
+ Adapter->NdisMiniportBlock.StatusCompleteHandler= MiniStatusComplete;
+
/*
* 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 );
- return (NTSTATUS)NdisStatus;
+ return NdisStatus;
}
- /* Set handlers (some NDIS macros require these) */
-
- Adapter->NdisMiniportBlock.EthRxCompleteHandler = EthFilterDprIndicateReceiveComplete;
- Adapter->NdisMiniportBlock.EthRxIndicateHandler = EthFilterDprIndicateReceive;
- Adapter->NdisMiniportBlock.SendCompleteHandler = MiniSendComplete;
- Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable;
- Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete;
- Adapter->NdisMiniportBlock.TDCompleteHandler = MiniTransferDataComplete;
- Adapter->NdisMiniportBlock.PacketIndicateHandler= MiniIndicateReceivePacket;
- Adapter->NdisMiniportBlock.StatusHandler = MiniStatus;
- Adapter->NdisMiniportBlock.StatusCompleteHandler= MiniStatusComplete;
+ if (SelectedMediumIndex >= MEDIA_ARRAY_SIZE)
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("MiniportInitialize() failed for an adapter\n"));
+ ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
+ return NDIS_STATUS_UNSUPPORTED_MEDIA;
+ }
Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex];
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)
Adapter->LookaheadBuffer = NULL;
}
ExInterlockedRemoveEntryList( &Adapter->ListEntry, &AdapterListLock );
- return (NTSTATUS)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;
+ Timeout.QuadPart = (LONGLONG)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);
RemoveEntryList(&Adapter->ListEntry);
KeReleaseSpinLock(&AdapterListLock, OldIrql);
+ KeCancelTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
+
(*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.HaltHandler)(Adapter);
if (Adapter->LookaheadBuffer)
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;
+}
+
\f
NTSTATUS
NTAPI
Status = IoGetDeviceProperty(PhysicalDeviceObject, DevicePropertyDriverKeyName,
0, NULL, &DriverKeyLength);
- if (Status != STATUS_BUFFER_TOO_SMALL)
+ 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"));
return Status;
Adapter->NdisMiniportBlock.OldPnPDeviceState = 0;
Adapter->NdisMiniportBlock.PnPDeviceState = NdisPnPDeviceAdded;
- KeInitializeDpc(&Adapter->NdisMiniportBlock.DeferredDpc, MiniportDpc, (PVOID)Adapter);
+ KeInitializeTimer(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Timer);
+ KeInitializeDpc(&Adapter->NdisMiniportBlock.WakeUpDpcTimer.Dpc, MiniportHangDpc, Adapter);
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
*MiniportPtr = Miniport;
Miniport->DriverObject->MajorFunction[IRP_MJ_PNP] = NdisIDispatchPnp;
+ Miniport->DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = NdisIShutdown;
Miniport->DriverObject->DriverExtension->AddDevice = NdisIAddDevice;
return NDIS_STATUS_SUCCESS;
IN NDIS_HANDLE MiniportAdapterHandle,
IN NDIS_STATUS Status)
{
- (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->SetCompleteHandler)(MiniportAdapterHandle, Status);
+ PLOGICAL_ADAPTER Adapter =
+ (PLOGICAL_ADAPTER)MiniportAdapterHandle;
+ KIRQL OldIrql;
+ ASSERT(Adapter);
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+ (Adapter->NdisMiniportBlock.SetCompleteHandler)(MiniportAdapterHandle, Status);
+ KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+ Adapter->MiniportBusy = FALSE;
+ KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+ KeLowerIrql(OldIrql);
}
\f
* 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"));
}