mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
354 lines
10 KiB
354 lines
10 KiB
/*+
|
|
* file: monitor.c
|
|
*
|
|
* Copyright (C) 1992-1995 by
|
|
* Digital Equipment Corporation, Maynard, Massachusetts.
|
|
* All rights reserved.
|
|
*
|
|
* This software is furnished under a license and may be used and copied
|
|
* only in accordance of the terms of such license and with the
|
|
* inclusion of the above copyright notice. This software or any other
|
|
* copies thereof may not be provided or otherwise made available to any
|
|
* other person. No title to and ownership of the software is hereby
|
|
* transferred.
|
|
*
|
|
* The information in this software is subject to change without notice
|
|
* and should not be construed as a commitment by digital equipment
|
|
* corporation.
|
|
*
|
|
* Digital assumes no responsibility for the use or reliability of its
|
|
* software on equipment which is not supplied by digital.
|
|
*
|
|
*
|
|
* Abstract: This file is part of the NDIS 4.0 miniport driver for DEC's
|
|
* DC21X4 Ethernet adapter.
|
|
*
|
|
* Author: Philippe Klein
|
|
*
|
|
* Revision History:
|
|
*
|
|
* phk 28-Aug-1994 initial entry
|
|
*
|
|
-*/
|
|
|
|
#include <precomp.h>
|
|
|
|
|
|
|
|
|
|
|
|
/*+
|
|
*
|
|
* DC21X4ModerateInterrupt
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Enable/Disable Rcv & Txm interrups based on the
|
|
* Rcv+Txm frames/second rate
|
|
*
|
|
* Arguments:
|
|
*
|
|
* Adapter
|
|
*
|
|
-*/
|
|
extern
|
|
VOID
|
|
DC21X4ModerateInterrupt (
|
|
IN PVOID Systemspecific1,
|
|
IN PDC21X4_ADAPTER Adapter,
|
|
IN PVOID Systemspecific2,
|
|
IN PVOID Systemspecific3
|
|
)
|
|
{
|
|
|
|
INT FrameCount;
|
|
INT FrameRate;
|
|
INT InterruptRate;
|
|
ULONG CFDA_Data;
|
|
|
|
|
|
//snapshot the number of frames processed and the number of
|
|
// interrupt handled during the last monitor interval
|
|
|
|
FrameCount = Adapter->GeneralMandatory[GM_RECEIVE_OK]
|
|
+ Adapter->GeneralMandatory[GM_RECEIVE_ERROR]
|
|
+ Adapter->GeneralMandatory[GM_TRANSMIT_OK]
|
|
+ Adapter->GeneralMandatory[GM_TRANSMIT_ERROR];
|
|
|
|
FrameRate = FrameCount - Adapter->FrameCount;
|
|
|
|
InterruptRate = Adapter->InterruptCount - Adapter->LastInterruptCount;
|
|
|
|
//save the snapshots
|
|
|
|
Adapter->FrameCount = FrameCount;
|
|
Adapter->LastInterruptCount = Adapter->InterruptCount;
|
|
|
|
|
|
if (InterruptRate > Adapter->InterruptThreshold) {
|
|
switch (Adapter->InterruptModeration) {
|
|
|
|
case NoInterruptMasked:
|
|
|
|
//Mask the Txm Interrupts
|
|
Adapter->InterruptModeration = TxmInterruptMasked;
|
|
|
|
Adapter->InterruptMask &= ~(DC21X4_TXM_INTERRUPTS);
|
|
|
|
DC21X4_WRITE_PORT(
|
|
DC21X4_INTERRUPT_MASK,
|
|
Adapter->InterruptMask
|
|
);
|
|
|
|
//Start the built_in timer to poll the Txm descriptor ring
|
|
|
|
// If the adapter is in Snooze mode,
|
|
// switch to regular mode to enable the
|
|
// built-in timer
|
|
|
|
if (Adapter->PciDriverArea & CFDA_SNOOZE_MODE) {
|
|
|
|
CFDA_Data = Adapter->PciDriverArea & ~CFDA_SNOOZE_MODE;
|
|
|
|
NdisWritePciSlotInformation(
|
|
Adapter->MiniportAdapterHandle,
|
|
Adapter->SlotNumber,
|
|
PCI_CFDA_OFFSET,
|
|
&CFDA_Data,
|
|
sizeof(CFDA_Data)
|
|
);
|
|
}
|
|
|
|
Adapter->Polling = Adapter->TxmPolling;
|
|
DC21X4_WRITE_PORT(
|
|
DC21X4_TIMER,
|
|
Adapter->Polling
|
|
);
|
|
break;
|
|
|
|
case TxmInterruptMasked:
|
|
|
|
//Mask the Rcv Interrupts
|
|
Adapter->InterruptModeration = TxmRcvInterruptMasked;
|
|
|
|
Adapter->InterruptMask &= ~(DC21X4_RCV_INTERRUPTS);
|
|
|
|
DC21X4_WRITE_PORT(
|
|
DC21X4_INTERRUPT_MASK,
|
|
Adapter->InterruptMask
|
|
);
|
|
|
|
//Restart the built_in timer to poll the Rcv & Txm descriptor rings
|
|
|
|
Adapter->Polling = Adapter->RcvTxmPolling;
|
|
DC21X4_WRITE_PORT(
|
|
DC21X4_TIMER,
|
|
Adapter->Polling
|
|
);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
else if (FrameRate < Adapter->FrameThreshold) {
|
|
switch (Adapter->InterruptModeration) {
|
|
|
|
case TxmRcvInterruptMasked:
|
|
|
|
//Demask the Rcv Interrupts
|
|
|
|
Adapter->InterruptModeration = TxmInterruptMasked;
|
|
|
|
Adapter->InterruptMask |= DC21X4_RCV_INTERRUPTS;
|
|
|
|
DC21X4_WRITE_PORT(
|
|
DC21X4_INTERRUPT_MASK,
|
|
Adapter->InterruptMask
|
|
);
|
|
|
|
//Restart the built_in timer to poll the Txm descriptor ring
|
|
Adapter->Polling = Adapter->TxmPolling;
|
|
DC21X4_WRITE_PORT(
|
|
DC21X4_TIMER,
|
|
Adapter->Polling
|
|
);
|
|
break;
|
|
|
|
case TxmInterruptMasked:
|
|
|
|
//Demask the Txm Interrupts
|
|
Adapter->InterruptModeration = NoInterruptMasked;
|
|
|
|
Adapter->InterruptMask |= DC21X4_TXM_INTERRUPTS;
|
|
|
|
DC21X4_WRITE_PORT(
|
|
DC21X4_INTERRUPT_MASK,
|
|
Adapter->InterruptMask
|
|
);
|
|
|
|
//Stop the Polling timer
|
|
|
|
Adapter->Polling = 0;
|
|
|
|
DC21X4_WRITE_PORT(
|
|
DC21X4_TIMER,
|
|
Adapter->Polling
|
|
);
|
|
|
|
if (Adapter->PciDriverArea & CFDA_SNOOZE_MODE) {
|
|
|
|
//set to the initial snooze mode
|
|
|
|
NdisWritePciSlotInformation(
|
|
Adapter->MiniportAdapterHandle,
|
|
Adapter->SlotNumber,
|
|
PCI_CFDA_OFFSET,
|
|
&Adapter->PciDriverArea,
|
|
sizeof(Adapter->PciDriverArea)
|
|
);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
//Restart the interrupt monitor timer
|
|
|
|
NdisMSetTimer(
|
|
&Adapter->MonitorTimer,
|
|
INT_MONITOR_PERIOD
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*+
|
|
*
|
|
* DC21X4CheckforHang
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* The DC21X4CheckforHang routine verifies that no unprocessed descriptor
|
|
* are left due to the interrupt synchronization on PCI where the
|
|
* interrupt posted by DC21X4 can be handled before the associated
|
|
* descriptor has been effectively closed into memory.
|
|
*
|
|
* The algorithm is as follows:
|
|
*
|
|
* if "current" Rx descriptor is owned by the host
|
|
* if current Rx_frame_count == snapshoted Rx_frame_count
|
|
* generate an interrupt
|
|
* else
|
|
* snashots the current Rx_frame_count
|
|
*
|
|
* if "current" Tx descriptor is owned by the host
|
|
* if current Tx_frame_count == snapshoted Tx_frame_count
|
|
* generate an interrupt
|
|
* else
|
|
* snashots the current Tx_frame_count
|
|
*
|
|
* Arguments:
|
|
*
|
|
* Adapter
|
|
*
|
|
* Return Value:
|
|
*
|
|
* None
|
|
*
|
|
-*/
|
|
extern
|
|
BOOLEAN
|
|
DC21X4CheckforHang(
|
|
IN NDIS_HANDLE MiniportAdapterContext
|
|
)
|
|
{
|
|
|
|
PDC21X4_ADAPTER Adapter;
|
|
INT TransmitFrameCount;
|
|
INT ReceiveFrameCount;
|
|
|
|
PDC21X4_RECEIVE_DESCRIPTOR ReceiveDescriptor;
|
|
PDC21X4_TRANSMIT_DESCRIPTOR TransmitDescriptor;
|
|
|
|
BOOLEAN GenerateInterrupt = FALSE;
|
|
|
|
Adapter = (PDC21X4_ADAPTER)MiniportAdapterContext;
|
|
|
|
if (Adapter->Polling) {
|
|
return FALSE;
|
|
}
|
|
|
|
ReceiveDescriptor = Adapter->DequeueReceiveDescriptor;
|
|
|
|
if ((ReceiveDescriptor->Status & DC21X4_RDES_OWN_BIT) == DESC_OWNED_BY_SYSTEM ) {
|
|
|
|
ReceiveFrameCount = Adapter->GeneralMandatory[GM_RECEIVE_OK]
|
|
+ Adapter->GeneralMandatory[GM_RECEIVE_ERROR];
|
|
|
|
GenerateInterrupt = (ReceiveFrameCount == Adapter->ReceiveFrameCount);
|
|
|
|
Adapter->ReceiveFrameCount = ReceiveFrameCount;
|
|
|
|
}
|
|
|
|
TransmitDescriptor = Adapter->DequeueTransmitDescriptor;
|
|
|
|
if (Adapter->GeneralOptional[GO_TRANSMIT_QUEUE_LENGTH] &&
|
|
((TransmitDescriptor->Status & DC21X4_TDES_OWN_BIT) == DESC_OWNED_BY_SYSTEM)) {
|
|
|
|
TransmitFrameCount = Adapter->GeneralMandatory[GM_TRANSMIT_OK]
|
|
+ Adapter->GeneralMandatory[GM_TRANSMIT_ERROR];
|
|
|
|
GenerateInterrupt = GenerateInterrupt ||
|
|
(TransmitFrameCount == Adapter->TransmitFrameCount);
|
|
|
|
Adapter->TransmitFrameCount = TransmitFrameCount;
|
|
|
|
}
|
|
|
|
if (GenerateInterrupt) {
|
|
|
|
|
|
switch (Adapter->DeviceId) {
|
|
|
|
case DC21040_CFID:
|
|
|
|
//Stop/start the Txm process to generate an Txm interrupt
|
|
#if _DBG
|
|
DbgPrint("Stop/Start Txm\n");
|
|
#endif
|
|
DC21X4_WRITE_PORT(
|
|
DC21X4_OPERATION_MODE,
|
|
Adapter->OperationMode & ~(DC21X4_TXM_START)
|
|
);
|
|
|
|
DC21X4_WRITE_PORT(
|
|
DC21X4_OPERATION_MODE,
|
|
Adapter->OperationMode
|
|
);
|
|
break;
|
|
|
|
default:
|
|
|
|
// Start the DC21X4 built_in timer to generate
|
|
// an Timer_expired interrupt
|
|
|
|
DC21X4_WRITE_PORT(
|
|
DC21X4_TIMER,
|
|
1
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|