Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

512 lines
11 KiB

#include <ndis.h>
#include "82595.h"
#include "eprohw.h"
#include "eprosw.h"
#include "epro.h"
#include "eprodbg.h"
// Global data
NDIS_MINIPORT_CHARACTERISTICS EPro_Miniport_Char;
EPRO_DRIVER EProMiniportDriver={0};
NDIS_STATUS EProSelReset(PEPRO_ADAPTER adapter)
/*++
Routine Description:
This does a SEL-RESET of the i82595 chip. Read the 82595 docs
for more info on what this does.
Arguments:
adapter - pointer to our adapter structure
Return Values:
always returns NDIS_STATUS_SUCCESS
--*/
{
EPRO_ASSERT_BANK_0(adapter);
EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_SEL_RESET);
// according to 82595 prelim doc: wait 2 us after sel reset before
// accessing the 82595
NdisStallExecution(2);
EProEnableInterrupts((NDIS_HANDLE)adapter);
adapter->fHung = FALSE;
return(NDIS_STATUS_SUCCESS);
}
VOID
EProInitializeAdapterData(
IN PEPRO_ADAPTER adapter
)
/*++
Routine Description:
This routine initializes our adapter structure - setting default
values, zeroing fields, etc. This is called on adapter initialization
and adapter reset.
Arguments:
A pointer to the adapter structure to clear.
Return Values:
none
--*/
{
UINT i;
adapter->CurrentHardwareStatus = NdisHardwareStatusReady;
adapter->vendorID[0] = EPRO_VENDOR_ID_L;
adapter->vendorID[1] = EPRO_VENDOR_ID_M;
adapter->vendorID[2] = EPRO_VENDOR_ID_H;
adapter->CurrentPacketFilter = 0;
// hack to get around wrapper bug:
// adapter->RXLookAheadSize = 0;
//
adapter->RXLookAheadSize = 256;
adapter->FramesXmitOK = 0;
adapter->FramesRcvOK = 0;
adapter->FramesXmitErr = 0;
adapter->FramesRcvErr = 0;
adapter->FramesMissed = 0;
adapter->FrameAlignmentErrors = 0;
adapter->FramesXmitOneCollision = 0;
adapter->FramesXmitManyCollisions = 0;
adapter->CurrentTXBuf = &adapter->TXBuf[0];
adapter->TXChainStart = NULL;
// Packet filter settings...
//
adapter->fPromiscuousEnable = FALSE;
adapter->fBroadcastEnable = FALSE;
adapter->fMulticastEnable = FALSE;
adapter->fReceiveEnabled = FALSE;
adapter->NumMCAddresses = 0;
// Don't force 8-bit operation
//
adapter->Use8Bit = FALSE;
adapter->IntPending = EPRO_INT_NONE_PENDING;
adapter->fHung = FALSE;
// adapter->fTransmitInProgress = FALSE;
// Set up the TX buffers...
//
for (i = 0;i < EPRO_NUM_TX_BUFFERS; i++)
{
if (0 == i)
{
adapter->TXBuf[0].LastBuf = &adapter->TXBuf[EPRO_NUM_TX_BUFFERS - 1];
}
else
{
adapter->TXBuf[i].LastBuf = &adapter->TXBuf[i-1];
}
if ((EPRO_NUM_TX_BUFFERS - 1) == i)
{
adapter->TXBuf[i].NextBuf = &adapter->TXBuf[0];
}
else
{
adapter->TXBuf[i].NextBuf = &adapter->TXBuf[i + 1];
}
adapter->TXBuf[i].fEmpty = TRUE;
adapter->TXBuf[i].TXBaseAddr = 0;
adapter->TXBuf[i].TXSendAddr = 0xffff;
}
}
VOID EProEnableInterrupts(IN NDIS_HANDLE miniportAdapterContext)
/*++
Routine Description:
The MiniportEnableInterrupt Handler for the card.
Arguments:
miniportAdapterContext - really a PEPRO_ADAPTER to our adapter structure
Return Value: none
--*/
{
PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
// If this isn't true, then NdisMSyncronizeWithInterrupt is broken
// or we've called a function which switches banks without syncronizing
// it...
EPRO_ASSERT_BANK_0(adapter);
EPRO_WR_PORT_UCHAR(adapter, I82595_INTMASK_REG,
adapter->CurrentInterruptMask);
}
VOID EProDisableInterrupts(IN NDIS_HANDLE miniportAdapterContext)
/*++
Routine Description:
The MiniportDisableInterrupts handler for the driver
Arguments:
miniportAdapterContext - really a pointer to our adapter structure
Return Values: none
--*/
{
PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
// If this isn't true, then NdisMSyncronizeWithInterrupt is broken
// or we've called a function which switches banks without syncronizing
// it...
EPRO_ASSERT_BANK_0(adapter);
// mask all int's
EPRO_WR_PORT_UCHAR(adapter, I82595_INTMASK_REG,
(adapter->CurrentInterruptMask | 0x0f));
}
VOID EProHalt(IN NDIS_HANDLE miniportAdapterContext)
/*++
Routine Description:
This is the function which halts the 82595 chip and disables the
adapter - frees hardware resources, etc.
Arguments:
miniportAdapterContext - pointer to our adapter structure
Returns: nothing
--*/
{
PEPRO_ADAPTER adapter = (EPRO_ADAPTER *)miniportAdapterContext;
// Shut down the card - disable receives.
EProReceiveDisable(adapter);
// There won't be any more interrupts
NdisMDeregisterInterrupt(&adapter->Interrupt);
// Pause, wait for pending DPC stuff to clear... Random number stolen
// from the NE2000 driver...
NdisStallExecution(250000);
// Unmap our IO ports
NdisMDeregisterIoPortRange(adapter->MiniportAdapterHandle,
(ULONG)adapter->IoBaseAddr,
0x10,
(PVOID)adapter->IoPAddr);
// Free up our adapter structure...
NdisFreeMemory(adapter, sizeof(EPRO_ADAPTER), 0);
}
NDIS_STATUS EProReset(OUT PBOOLEAN fAddressingReset,
IN NDIS_HANDLE miniportAdapterContext)
/*++
Routine Description:
This is the MiniportReset handler for the EPro driver
Arguments:
fAddressingReset - Do we need to be re-told our MC address list?
currently we say yes, although probably we don't
have to be told this (the driver saves it)
Return Values:
the return from EProSelReset (always NDIS_STATUS_SUCCESS)
--*/
{
PEPRO_ADAPTER adapter = (EPRO_ADAPTER *)miniportAdapterContext;
// Okay, we don't want to get any interrupts anymore.
EProDisableInterrupts(adapter);
EProReceiveDisable(adapter);
// clear out TX structures...
EProInitializeAdapterData(adapter);
// We probably can set this to false -- TODO
*fAddressingReset = TRUE;
return(EProSelReset(adapter));
}
BOOLEAN EProCheckForHang(IN NDIS_HANDLE miniportAdapterContext)
/*++
Routine Description:
This is the MiniportCheckForHang handler for the driver.
It does absolutely nothing right now.
Arguments:
miniportAdapterContext - right now a pointer to our adapter structure
Return Value:
--*/
{
PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
if (adapter->fHung)
{
return(TRUE);
}
return(FALSE);
}
VOID EProHandleInterrupt(
IN NDIS_HANDLE miniportAdapterContext)
/*++
Routine Description:
This is the function that gets called at DPC level in response
to a hardware interrupt. It is queued by the wrapper's ISR routines.
Interrupts have been disabled when this routine is called.
Arguments:
miniportAdapterContext - really a pointer to our adapter structure
Return Value:
none
--*/
{
PEPRO_ADAPTER adapter = (EPRO_ADAPTER *)miniportAdapterContext;
UCHAR whichInt;
BOOLEAN fFoundInts, fFoundRX = FALSE;
// verify bank 0
EPRO_ASSERT_BANK_0(adapter);
do
{
fFoundInts = FALSE;
// Read in the int mask
//
EPRO_RD_PORT_UCHAR(adapter, I82595_STATUS_REG, &whichInt);
// quick out if there are no ints pending...
if (!(whichInt & 0x0f))
{
break;
}
// acknowlege interrupts - writing a 1 over the int flag clears it
EPRO_WR_PORT_UCHAR(adapter, I82595_STATUS_REG, whichInt);
if (whichInt & I82595_TX_INT_RCVD)
{
fFoundInts = TRUE;
if (adapter->TXChainStart != NULL)
{
EProCheckTransmitCompletion(adapter, adapter->TXChainStart);
}
}
// if (whichInt & I82595_TX_INT_RCVD)
// {
// fFoundInts = TRUE;
// if (adapter->TXChainStart != NULL)
// {
// while (EProCheckTransmitCompletion(adapter, adapter->TXChainStart))
// ;
// }
// }
if (whichInt & I82595_RX_INT_RCVD)
{
fFoundInts = TRUE;
if (EProHandleReceive(adapter) > 0)
{
fFoundRX = TRUE;
}
}
if (whichInt & I82595_EXEC_INT_RCVD)
{
fFoundInts = TRUE;
EProSetInterruptMask(adapter, EPRO_DEFAULT_INTERRUPTS);
switch(adapter->IntPending)
{
case EPRO_INT_MC_SET_PENDING:
((PEPRO_TRANSMIT_BUFFER)adapter->IntContext)->fEmpty = TRUE;
EPRO_DPRINTF_INTERRUPT(("Set COMPLETED!"));
NdisMSetInformationComplete(
adapter->MiniportAdapterHandle,
NDIS_STATUS_SUCCESS);
break;
// default:
// EPRO_ASSERT(FALSE); // we shouldn't hit this...
}
// clear the pending interrupt...
//
adapter->IntPending = 0;
adapter->IntContext = NULL;
}
} while ((fFoundInts == TRUE) && !adapter->fHung);
if (fFoundRX)
{
NdisMEthIndicateReceiveComplete(adapter->MiniportAdapterHandle);
}
}
void
EProISR(
OUT PBOOLEAN interruptRecognized,
OUT PBOOLEAN queueMiniportHandleInterrupt,
IN NDIS_HANDLE miniportAdapterContext)
{
EPRO_DPRINTF_INTERRUPT(("ISR"));
*interruptRecognized = TRUE;
*queueMiniportHandleInterrupt = FALSE;
}
BOOLEAN EProSyncSetInterruptMask(PVOID context)
{
PEPRO_ADAPTER adapter = ((PEPRO_SETINTERRUPT_CONTEXT)context)->Adapter;
UCHAR newMask = ((PEPRO_SETINTERRUPT_CONTEXT)context)->NewMask;
// unmask everyone...
adapter->CurrentInterruptMask &= 0xf0;
// now mask the ones we don't want
adapter->CurrentInterruptMask |= newMask;
EPRO_ASSERT_BANK_0(adapter);
EPRO_WR_PORT_UCHAR(adapter, I82595_INTMASK_REG,
adapter->CurrentInterruptMask);
return(TRUE);
}
// Poll the exec-states reg (0,1), waiting for any execution to finish...
BOOLEAN EProWaitForExeDma(PEPRO_ADAPTER adapter)
{
UINT i;
UCHAR result;
// status reg is in bank 0
EPRO_ASSERT_BANK_0(adapter);
for (i=0;i<I82595_SPIN_TIMEOUT;i++) {
// make sure the dma is idle
EPRO_RD_PORT_UCHAR(adapter, I82595_STATUS_REG, &result);
if (!(result&I82595_EXEC_STATE)) {
if (result & I82595_EXEC_INT_RCVD) {
// clear the exec int if it's high...
EPRO_WR_PORT_UCHAR(adapter, I82595_STATUS_REG,
I82595_EXEC_INT_RCVD);
}
return(TRUE);
}
NdisStallExecution(1);
}
return(FALSE);
}
BOOLEAN EProReceiveEnable(PEPRO_ADAPTER adapter)
{
UINT i = 0;
UCHAR result;
adapter->RXCurrentAddress = 0 | (((USHORT)EPRO_RX_LOWER_LIMIT) << 8);
// EPRO_ASSERT(!adapter->fReceiveEnabled);
// don't enable if we're already enabled.
if (adapter->fReceiveEnabled)
{
return(TRUE);
}
// bank0
// EPRO_SWITCH_BANK_0(adapter);
//
EPRO_ASSERT_BANK_0(adapter);
EPRO_WR_PORT_USHORT(adapter, I82595_RX_STOP_REG, 0 | (((USHORT)EPRO_RX_UPPER_LIMIT) << 8));
EPRO_WR_PORT_USHORT(adapter, I82595_RX_BAR_REG, 0 | (((USHORT)EPRO_RX_LOWER_LIMIT) << 8));
//
// validate registers...
//
EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_RCV_ENABLE);
adapter->fReceiveEnabled = TRUE;
return(TRUE);
}
BOOLEAN EProReceiveDisable(PEPRO_ADAPTER adapter)
{
UINT i = 0;
UCHAR result;
// bank0
// EPRO_SWITCH_BANK_0(adapter);
EPRO_ASSERT_BANK_0(adapter);
EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_STOP_RCV);
adapter->fReceiveEnabled = FALSE;
return(TRUE);
}
//VOID EProTimerFunc(IN PVOID foo1, IN PVOID context, IN PVOID foo2, IN PVOID foo3)
//{
// EProHandleInterrupt((NDIS_HANDLE)context);
//
// queue another timer...
// NdisMSetTimer(&(((PEPRO_ADAPTER)context)->MiniportTimer), 10);
//}