{
PROTOCOL_BINDING *Protocol = (PROTOCOL_BINDING *)BindAdapterContext;
+ if (!NT_SUCCESS(Status)) return;
+
/* Put protocol binding struct on global list */
ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
}
* - XXX ATM, this only handles loopback packets - is that its designed function?
*/
{
- KIRQL OldIrql;
UINT BufferedLength;
UINT PacketLength;
+ KIRQL OldIrql;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
*/
{
KIRQL OldIrql;
- BOOLEAN QueueWorkItem = FALSE;
- NDIS_STATUS NdisStatus;
PADAPTER_BINDING AdapterBinding;
PLOGICAL_ADAPTER Adapter;
PNDIS_REQUEST_MAC_BLOCK MacBlock = (PNDIS_REQUEST_MAC_BLOCK)NdisRequest->MacReserved;
NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
{
- if(Adapter->MiniportBusy)
- QueueWorkItem = TRUE;
- else
- {
- NDIS_DbgPrint(MAX_TRACE, ("Setting adapter 0x%x to busy\n"));
- Adapter->MiniportBusy = TRUE;
- }
- }
-
- /* MiniQueueWorkItem must be called at IRQL >= DISPATCH_LEVEL */
- if (QueueWorkItem)
- {
- MiniQueueWorkItem(Adapter, NdisWorkItemRequest, (PVOID)NdisRequest);
- KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
- return NDIS_STATUS_PENDING;
+ if (Adapter->MiniportBusy) {
+ MiniQueueWorkItem(Adapter, NdisWorkItemRequest, (PVOID)NdisRequest);
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+ return NDIS_STATUS_PENDING;
+ }
}
-
KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
- NdisStatus = MiniDoRequest(&Adapter->NdisMiniportBlock, NdisRequest);
-
- NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
- KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
- {
- NDIS_DbgPrint(MAX_TRACE, ("Setting adapter 0x%x to free\n"));
- Adapter->MiniportBusy = FALSE;
-
- if (Adapter->WorkQueueHead)
- KeInsertQueueDpc(&Adapter->NdisMiniportBlock.DeferredDpc, NULL, NULL);
- }
- KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
-
- return NdisStatus;
+ return MiniDoRequest(Adapter, NdisRequest);
}
\f
* MacBindingHandle = Adapter binding handle
* Packet = Pointer to NDIS packet descriptor
* RETURNS:
- * NDIS_STATUS_SUCCESS always
+ * NDIS_STATUS_SUCCESS if the packet was successfully sent
+ * NDIS_STATUS_PENDING if the miniport was busy or a serialized miniport returned NDIS_STATUS_RESOURCES
* NOTES:
* TODO:
- * - Fix return values
- * - Should queue packet if miniport returns NDIS_STATUS_RESOURCES
- * - Queue packets directly on the adapters when possible (i.e.
- * when miniports not busy)
* - Break this up
*/
{
- KIRQL RaiseOldIrql, SpinOldIrql;
- BOOLEAN QueueWorkItem = FALSE;
- NDIS_STATUS NdisStatus;
+ KIRQL SpinOldIrql, RaiseOldIrql;
PADAPTER_BINDING AdapterBinding;
PLOGICAL_ADAPTER Adapter;
+ NDIS_STATUS NdisStatus;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
/* XXX what is this crazy black magic? */
Packet->Reserved[0] = (ULONG_PTR)MacBindingHandle;
- /*
- * Acquire this lock in order to see if the miniport is busy.
- * If it is not busy, we mark it as busy and release the lock.
- * Else we don't do anything because we have to queue a workitem
- * anyway.
- */
- NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
- KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &SpinOldIrql);
- {
- /*
- * if the miniport is marked as busy, we queue the packet as a work item,
- * else we send the packet directly to the miniport. Sending to the miniport
- * makes it busy.
- */
- if (Adapter->MiniportBusy)
- QueueWorkItem = TRUE;
- else
- {
- NDIS_DbgPrint(MAX_TRACE, ("Setting adapter 0x%x to busy\n"));
- Adapter->MiniportBusy = TRUE;
- }
- }
- KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, SpinOldIrql);
-
/*
* Test the packet to see if it is a MAC loopback.
*
* If dest MAC address of packet == MAC address of adapter,
* this is a loopback frame.
*/
+
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &SpinOldIrql);
+
if ((Adapter->NdisMiniportBlock.MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) &&
MiniAdapterHasAddress(Adapter, Packet))
{
- NDIS_DbgPrint(MIN_TRACE, ("Looping packet.\n"));
-
- if (QueueWorkItem)
- {
- MiniQueueWorkItem(Adapter, NdisWorkItemSendLoopback, (PVOID)Packet);
- return NDIS_STATUS_PENDING;
- }
-
- KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
- {
- /*
- * atm this *only* handles loopback packets - it calls MiniIndicateData to
- * send back to the protocol. FIXME: this will need to be adjusted a bit.
- * Also, I'm not sure you really have to be at dispatch level for this. It
- * might use a ReceivePackets handler, which can run <= DISPATCH_LEVEL.
- */
- NdisStatus = ProIndicatePacket(Adapter, Packet);
-
- NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
- KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
- {
- NDIS_DbgPrint(MAX_TRACE, ("Setting adapter 0x%x to free\n"));
- Adapter->MiniportBusy = FALSE;
-
- if (Adapter->WorkQueueHead)
- KeInsertQueueDpc(&Adapter->NdisMiniportBlock.DeferredDpc, NULL, NULL);
- else
- NDIS_DbgPrint(MID_TRACE,("Failed to insert packet into work queue\n"));
- }
- KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+ if(Adapter->MiniportBusy) {
+ MiniQueueWorkItem(Adapter, NdisWorkItemSendLoopback, Packet);
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, SpinOldIrql);
+ return NDIS_STATUS_PENDING;
}
- KeLowerIrql(RaiseOldIrql);
- return NdisStatus;
- }
- else
- NDIS_DbgPrint(MID_TRACE,("Not a loopback packet\n"));
-
- /* This is a normal send packet, not a loopback packet. */
- if (QueueWorkItem)
- {
- MiniQueueWorkItem(Adapter, NdisWorkItemSend, (PVOID)Packet);
- NDIS_DbgPrint(MAX_TRACE, ("Queued a work item and returning\n"));
- return NDIS_STATUS_PENDING;
- }
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, SpinOldIrql);
- ASSERT(Adapter->NdisMiniportBlock.DriverHandle);
-
- /*
- * Call the appropriate send handler
- *
- * If a miniport provides a SendPackets handler, we always call it. If not, we call the
- * Send handler.
- */
- if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
- {
- 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, &Packet, 1);
- }
- 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, &Packet, 1);
- }
- KeLowerIrql(RaiseOldIrql);
+ return ProIndicatePacket(Adapter, Packet);
+ } else {
+ if(Adapter->MiniportBusy) {
+ MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet);
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, SpinOldIrql);
+ return NDIS_STATUS_PENDING;
}
- /* SendPackets handlers return void - they always "succeed" */
- NdisStatus = NDIS_STATUS_SUCCESS;
- }
- else
- {
- /* XXX FIXME THIS IS WRONG */
- /* uh oh... forgot why i thought that... */
- 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, Packet, 0);
- NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
- }
- else
- {
- /* Send handlers always run at DISPATCH_LEVEL so we raise here */
- KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
-
- NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
- NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)(
- Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, 0);
- NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
- if( NdisStatus != NDIS_STATUS_PENDING ) {
- Adapter->MiniportBusy = FALSE;
- }
- KeLowerIrql(RaiseOldIrql);
- }
- }
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, SpinOldIrql);
- /* XXX why the hell do we do this? */
- NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
- KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &SpinOldIrql);
- {
- if (Adapter->WorkQueueHead)
+ if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)
{
- KeInsertQueueDpc(&Adapter->NdisMiniportBlock.DeferredDpc, NULL, NULL);
- NDIS_DbgPrint(MAX_TRACE, ("MiniportDpc queued; returning NDIS_STATUS_SUCCESS\n"));
- }
- }
- KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, SpinOldIrql);
-
- NDIS_DbgPrint(MAX_TRACE, ("returning 0x%x\n", NdisStatus));
- return NdisStatus;
+ 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, &Packet, 1);
+ NdisStatus = NDIS_GET_PACKET_STATUS(Packet);
+ } 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, &Packet, 1);
+ }
+ KeLowerIrql(RaiseOldIrql);
+
+ NdisStatus = NDIS_GET_PACKET_STATUS(Packet);
+ if( NdisStatus == NDIS_STATUS_RESOURCES ) {
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &SpinOldIrql);
+ MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet);
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, SpinOldIrql);
+ NdisStatus = NDIS_STATUS_PENDING;
+ }
+ }
+
+ return NdisStatus;
+ } else {
+ 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, Packet, 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, Packet, 0);
+ NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
+ KeLowerIrql(RaiseOldIrql);
+ if( NdisStatus == NDIS_STATUS_RESOURCES ) {
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &SpinOldIrql);
+ MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet);
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, SpinOldIrql);
+ NdisStatus = NDIS_STATUS_PENDING;
+ }
+ }
+
+ return NdisStatus;
+ }
+ }
}
\f
{
PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
+ NDIS_STATUS Status;
+ KIRQL OldIrql;
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
return NDIS_STATUS_SUCCESS;
}
- return (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.TransferDataHandler)(
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+
+ Status = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.TransferDataHandler)(
Packet,
BytesTransferred,
Adapter->NdisMiniportBlock.MiniportAdapterContext,
MacReceiveContext,
ByteOffset,
BytesToTransfer);
+
+ KeLowerIrql(OldIrql);
+
+ return Status;
}
/* Put protocol binding struct on global list */
ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
}
-
- /*
else if(*Status != NDIS_STATUS_PENDING)
{
- // what to do here?
+ ExFreePool(Protocol);
+ ExFreePool(KeyInformation);
+ *NdisProtocolHandle = NULL;
+ return;
}
- */
}
ExFreePool(KeyInformation);