summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/elnkii/pend.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/ndis/elnkii/pend.c440
1 files changed, 440 insertions, 0 deletions
diff --git a/private/ntos/ndis/elnkii/pend.c b/private/ntos/ndis/elnkii/pend.c
new file mode 100644
index 000000000..b2d343852
--- /dev/null
+++ b/private/ntos/ndis/elnkii/pend.c
@@ -0,0 +1,440 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pend.c
+
+Abstract:
+
+ Multicast and filter functions for the NDIS 3.0 Etherlink II driver.
+
+Author:
+
+ Adam Barr (adamba) 30-Jul-1990
+ Aaron Ogus (aarono) 27-Sep-1991
+
+Environment:
+
+ Kernel mode, FSD
+
+Revision History:
+
+
+ Aaron Ogus (aarono) 27-Sep-1991
+ Changes to NdisRequest() format required changes to pending operations
+ Sean Selitrennikoff (seanse) Dec-1991
+ Changes to meet standard model for NDIS drivers.
+
+--*/
+
+#include <ndis.h>
+#include <efilter.h>
+#include "elnkhrd.h"
+#include "elnksft.h"
+
+
+VOID
+HandlePendingOperations(
+ IN PVOID SystemSpecific1,
+ IN PVOID DeferredContext, // will be a pointer to the adapter block
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ )
+
+/*++
+
+Routine Description:
+
+ Called by pending functions to process elements on the
+ pending queue.
+
+Arguments:
+
+ DeferredContext - will be a pointer to the adapter block
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PELNKII_ADAPTER AdaptP = ((PELNKII_ADAPTER)DeferredContext);
+ PELNKII_PEND_DATA PendOp;
+ PELNKII_OPEN TmpOpen;
+ NDIS_STATUS Status;
+
+ UNREFERENCED_PARAMETER(SystemSpecific1);
+ UNREFERENCED_PARAMETER(SystemSpecific2);
+ UNREFERENCED_PARAMETER(SystemSpecific3);
+
+ NdisAcquireSpinLock(&AdaptP->Lock);
+
+ AdaptP->References++;
+
+ //
+ // If an operation is being dispatched or a reset is running, exit.
+ //
+
+ if ((!AdaptP->ResetInProgress) && (AdaptP->PendOp == NULL)) {
+
+ for (;;) {
+
+ //
+ // We hold SpinLock here.
+ //
+
+ if (AdaptP->PendQueue != NULL) {
+
+ //
+ // Take the request off the queue and dispatch it.
+ //
+
+ PendOp = AdaptP->PendQueue;
+
+ AdaptP->PendQueue = PendOp->Next;
+
+ if (PendOp == AdaptP->PendQTail) {
+
+ AdaptP->PendQTail = NULL;
+
+ }
+
+ AdaptP->PendOp = PendOp;
+
+ NdisReleaseSpinLock(&AdaptP->Lock);
+
+ Status = ((PendOp->RequestType == NdisRequestClose) ||
+ (PendOp->RequestType == NdisRequestGeneric3)) ?
+ DispatchSetMulticastAddressList(AdaptP) :
+ DispatchSetPacketFilter(AdaptP);
+
+ TmpOpen = PendOp->Open;
+
+ if ((PendOp->RequestType != NdisRequestGeneric1) &&
+ (PendOp->RequestType != NdisRequestClose)) { // Close Adapter
+
+
+ //
+ // Complete it since it previously pended.
+ //
+
+ NdisCompleteRequest(PendOp->Open->NdisBindingContext,
+ PNDIS_REQUEST_FROM_PELNKII_PEND_DATA(PendOp),
+ Status);
+
+ }
+
+ //
+ // This will call CompleteClose if necessary.
+ //
+
+ NdisAcquireSpinLock(&AdaptP->Lock);
+
+ TmpOpen->ReferenceCount--;
+
+ if (AdaptP->ResetInProgress) {
+
+ //
+ // We have to stop processing requests.
+ //
+
+ break; // jump to BREAK_LOCATION
+ }
+
+ } else {
+
+ break; // jump to BREAK_LOCATION
+
+ }
+ }
+
+ //
+ // BREAK_LOCATION
+ //
+ // Hold Lock here.
+ //
+
+ AdaptP->PendOp = NULL;
+
+ if (AdaptP->ResetInProgress) {
+
+ //
+ // Exited due to a reset, indicate that the DPC
+ // handler is done for now.
+ //
+
+ AdaptP->References--;
+
+ NdisReleaseSpinLock(&AdaptP->Lock);
+
+ ElnkiiResetStageDone(AdaptP, MULTICAST_RESET);
+
+ return;
+ }
+
+ }
+
+ if (AdaptP->CloseQueue != NULL) {
+
+ PELNKII_OPEN OpenP;
+ PELNKII_OPEN TmpOpenP;
+ PELNKII_OPEN PrevOpenP;
+
+ //
+ // Check for an open that may have closed
+ //
+
+ OpenP = AdaptP->CloseQueue;
+ PrevOpenP = NULL;
+
+ while (OpenP != NULL) {
+
+ if (OpenP->ReferenceCount > 0) {
+
+ OpenP = OpenP->NextOpen;
+ PrevOpenP = OpenP;
+
+ continue;
+
+ }
+
+#if DBG
+
+ if (!OpenP->Closing) {
+
+ DbgPrint("BAD CLOSE: %d\n", OpenP->ReferenceCount);
+
+ DbgBreakPoint();
+
+ OpenP = OpenP->NextOpen;
+ PrevOpenP = OpenP;
+
+ continue;
+
+ }
+
+#endif
+
+
+ //
+ // The last reference is completed; a previous call to ElnkiiCloseAdapter
+ // will have returned NDIS_STATUS_PENDING, so things must be finished
+ // off now.
+ //
+
+ //
+ // Check if MaxLookAhead needs adjusting.
+ //
+
+ if (OpenP->LookAhead == AdaptP->MaxLookAhead) {
+
+ ElnkiiAdjustMaxLookAhead(AdaptP);
+
+ }
+
+ NdisReleaseSpinLock(&AdaptP->Lock);
+
+ NdisCompleteCloseAdapter (OpenP->NdisBindingContext, NDIS_STATUS_SUCCESS);
+
+ NdisAcquireSpinLock(&AdaptP->Lock);
+
+ //
+ // Remove from close list
+ //
+
+ if (PrevOpenP != NULL) {
+
+ PrevOpenP->NextOpen = OpenP->NextOpen;
+
+ } else {
+
+ AdaptP->CloseQueue = OpenP->NextOpen;
+ }
+
+ //
+ // Go to next one
+ //
+
+ TmpOpenP = OpenP;
+ OpenP = OpenP->NextOpen;
+
+ NdisFreeMemory(TmpOpenP, sizeof(ELNKII_OPEN), 0);
+
+ }
+
+ if ((AdaptP->CloseQueue == NULL) && (AdaptP->OpenQueue == NULL)) {
+
+ //
+ // We can stop the card.
+ //
+
+ CardStop(AdaptP);
+
+ }
+
+ }
+
+ ELNKII_DO_DEFERRED(AdaptP);
+
+}
+
+NDIS_STATUS
+DispatchSetPacketFilter(
+ IN PELNKII_ADAPTER AdaptP
+ )
+
+/*++
+
+Routine Description:
+
+ Sets the appropriate bits in the adapter filters
+ and modifies the card Receive Configuration Register if needed.
+
+Arguments:
+
+ AdaptP - Pointer to the adapter block
+
+Return Value:
+
+ The final status (always NDIS_STATUS_SUCCESS).
+
+Notes:
+
+ - Note that to receive all multicast packets the multicast
+ registers on the card must be filled with 1's. To be
+ promiscuous that must be done as well as setting the
+ promiscuous physical flag in the RCR. This must be done
+ as long as ANY protocol bound to this adapter has their
+ filter set accordingly.
+
+--*/
+
+
+{
+ UINT PacketFilter;
+
+ PacketFilter = ETH_QUERY_FILTER_CLASSES(AdaptP->FilterDB);
+
+ //
+ // See what has to be put on the card.
+ //
+
+ if (PacketFilter & (NDIS_PACKET_TYPE_ALL_MULTICAST | NDIS_PACKET_TYPE_PROMISCUOUS)) {
+
+ //
+ // need "all multicast" now.
+ //
+
+ CardSetAllMulticast(AdaptP); // fills it with 1's
+
+ } else {
+
+ //
+ // No longer need "all multicast".
+ //
+
+ DispatchSetMulticastAddressList(AdaptP);
+
+ }
+
+
+ //
+ // The multicast bit in the RCR should be on if ANY protocol wants
+ // multicast/all multicast packets (or is promiscuous).
+ //
+
+ if (PacketFilter & (NDIS_PACKET_TYPE_ALL_MULTICAST |
+ NDIS_PACKET_TYPE_MULTICAST |
+ NDIS_PACKET_TYPE_PROMISCUOUS)) {
+
+ AdaptP->NicReceiveConfig |= RCR_MULTICAST;
+
+ } else {
+
+ AdaptP->NicReceiveConfig &= ~RCR_MULTICAST;
+
+ }
+
+
+ //
+ // The promiscuous physical bit in the RCR should be on if ANY
+ // protocol wants to be promiscuous.
+ //
+
+ if (PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
+
+ AdaptP->NicReceiveConfig |= RCR_ALL_PHYS;
+
+ } else {
+
+ AdaptP->NicReceiveConfig &= ~RCR_ALL_PHYS;
+
+ }
+
+
+ //
+ // The broadcast bit in the RCR should be on if ANY protocol wants
+ // broadcast packets (or is promiscuous).
+ //
+
+ if (PacketFilter & (NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_PROMISCUOUS)) {
+
+ AdaptP->NicReceiveConfig |= RCR_BROADCAST;
+
+ } else {
+
+ AdaptP->NicReceiveConfig &= ~RCR_BROADCAST;
+
+ }
+
+
+ CardSetReceiveConfig(AdaptP);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+
+NDIS_STATUS
+DispatchSetMulticastAddressList(
+ IN PELNKII_ADAPTER AdaptP
+ )
+
+/*++
+
+Routine Description:
+
+ Sets the multicast list for this open
+
+Arguments:
+
+ AdaptP - Pointer to the adapter block
+
+Return Value:
+
+Implementation Note:
+
+ When invoked, we are to make it so that the multicast list in the filter
+ package becomes the multicast list for the adapter. To do this, we
+ determine the required contents of the NIC multicast registers and
+ update them.
+
+
+--*/
+{
+
+ //
+ // Update the local copy of the NIC multicast regs and copy them to the NIC
+ //
+
+ CardFillMulticastRegs(AdaptP);
+
+ CardCopyMulticastRegs(AdaptP);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+