📄 e100bexcard.cpp
字号:
//
// Parameters:
// None
// IRQL:
//
// Return Mode:
//
// Returns:
// TRUE - The receive unit is started
// FALSE - The receive unit is not started
// NOTE:
//
BOOLEAN E100bexCard::ReceiveUnitStarted()
{
// If the receiver is ready, return TRUE.
if (( USHORT(m_CSRStruc.ScbStatus) & SCB_RUS_MASK ) == SCB_RUS_READY)
{
return TRUE;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////
// E100bexCard::StartReceiveUnit
//
// This routine checks the status of the 82557's receive unit(RU),
// and starts the RU if it was not already active. However,
// before restarting the RU, the driver cleans up any recent
// pending receives (this is very important).
//
// Parameters:
// None
// IRQL:
//
// Return Mode:
//
// Returns:
// TRUE - If we indicated any receives during this function call
// FALSE - If we didn't indicate any receives
// NOTE:
//
VOID E100bexCard::StartReceiveUnit(PNDIS_PHYSICAL_ADDRESS pPhysAddr)
{
ASSERT( pPhysAddr );
// Wait for the SCB to clear before we set the general pointer
if ( FALSE == WaitScb() )
{
ASSERT(0);
}
// Set the SCB General Pointer to point the current Rfd
m_CSRStruc.ScbGeneralPointer = NdisGetPhysicalAddressLow(*pPhysAddr);
// Issue the SCB RU start command
IssueScbCommand(SCB_RUC_START, FALSE);
// wait for the command to be accepted
WaitScb();
UINT WaitCount = 80000;
// wait for RUS to be Ready
while (WaitCount != 0)
{
if (( USHORT(m_CSRStruc.ScbStatus) & SCB_RUS_MASK) == SCB_RUS_READY)
break;
NdisStallExecution(10);
WaitCount--;
}
if (!WaitCount)
{
TRACE("HARDWARE_NOT_RESPONDING");
}
#if DBG
// If we fall through, we have a problem.
if (WaitCount == 0)
TRACE("Failed, RU won't ready -- ScbStatus %08x\n", USHORT(m_CSRStruc.ScbStatus) );
#endif
}
////////////////////////////////////////////////////////////////////
// E100bexCard::IsInterrupting
//
// This routine checks if the card is interrupting (the interrupt line
// is high, and the interrupt is not masked.) If the interrupt line
// is already masked, then the driver is currently processing interrupts
//
// Parameters:
// None
// IRQL:
// DIRQL - called from Adapter class ISR
// Return Mode:
//
// Returns:
// TRUE - If the card is interrupting
// FALSE - Its not this card's interrupt or its masked
// NOTE:
//
BOOLEAN E100bexCard::IsInterrupting(void)
{
if ((!( UCHAR(m_CSRStruc.ScbCommandHigh) & SCB_INT_MASK)) &&
( USHORT(m_CSRStruc.ScbStatus) & SCB_ACK_MASK))
{
return TRUE;
}
else
{
return FALSE;
}
}
////////////////////////////////////////////////////////////////////
// E100bexCard::AckPendingInterrupts
//
// This routine reads the ScbStatus register and checks the reason
// for the interrupt. If there are no interrupts to process,
// returns FALSE. If there are pending interrupts, ack the
// interrupt and return TRUE.
//
// Parameters:
// None
// IRQL:
// Any - called from Adapter class DPC
// Return Mode:
//
// NOTE:
//
BOOLEAN E100bexCard::AckPendingInterrupts(void)
{
// Check the interrupt status bits of the SCB to determine the reason
// for the interrupt.
volatile USHORT AckCommand = USHORT(m_CSRStruc.ScbStatus);
TRACE3(("ScbStatus %04x\n", AckCommand))
TRACE2(("E100bexCard::AckPendingInterrupts, ScbStatus = %04x\n", AckCommand))
// Strip off the ACK bits.
AckCommand &= SCB_ACK_MASK;
// If there are no interrupts to process, then exit loop
if (!AckCommand)
{
return FALSE;
}
m_CSRStruc.ScbStatus = AckCommand;
return TRUE;
}
////////////////////////////////////////////////////////////////////
// E100bexCard::SetMcTimeoutFlag
//
// Set the McTimeoutFlag variable
//
// Parameters:
// none
// IRQL:
//
// Return Mode:
//
// NOTE:
// This McTimeoutFlag will determine whether the
// driver issues a periodic multicast command or not. Issuing a periodic
// multicast command will reset the 82557's internal receive state machine,
// and bring the 82557 out of a "Receive-lockup" state. This is a documented
// errata in the 82557 software developement manual.
// If the end user didn't over-ride the McTimeout flag, then it should be
// enabled only for 10mb operation, and only if the EEPROM indicates that
// this adapter has a potential rcv-lockup problem.
//
VOID E100bexCard::SetMcTimeoutFlag()
{
if (m_Ai.McTimeoutFlag == 2)
{
// Read the EEPROM flags register
USHORT EepromFlags = ReadEEprom(EEPROM_FLAGS_WORD_3);
if ((( m_Phy.GetCurrentLineSpeed() == 10) && (!(EepromFlags & EEPROM_FLAG_10MC))) ||
(( m_Phy.GetCurrentLineSpeed() == 100) && (!(EepromFlags & EEPROM_FLAG_100MC))))
{
m_Ai.McTimeoutFlag = 1;
}
else
{
m_Ai.McTimeoutFlag = 0;
}
}
TRACE("MC Timeout Flag = %x\n", m_Ai.McTimeoutFlag);
}
////////////////////////////////////////////////////////////////////
// E100bexCard::GetSharedMemorySize
//
// Get how much shared memory the E100bexCard needs.
//
// Parameters:
// none
// IRQL:
// Any
// Return Mode:
// Synchronous
// NOTE:
// The Adapter will call this method prior to allocating
// shared memory.
//
ULONG E100bexCard::GetSharedMemorySize(void)
{
// return the size of the data structures that reside in shared memory
// plus an additional 16 bytes (CARD_SHARED_MEM_ALIGNMENT) to paragraph align each structure
return
sizeof(SELF_TEST_STRUC) + CARD_SHARED_MEM_ALIGNMENT +
sizeof(DUMP_AREA_STRUC) + CARD_SHARED_MEM_ALIGNMENT +
sizeof(NON_TRANSMIT_CB) + CARD_SHARED_MEM_ALIGNMENT +
sizeof(ERR_COUNT_STRUC) + CARD_SHARED_MEM_ALIGNMENT ;
}
////////////////////////////////////////////////////////////////////
// E100bexCard::Setupsharedmemory
//
// Initalize E100bexCard data members with shared memory.
//
// Parameters:
// CbPhys - Physical address
// ShMem - KNdisSharedMemory object
// IRQL:
// Any
// Return Mode:
// Synchronous
// NOTE:
// The Adapter will call this method after allocating
// shared memory. The method will initialize the data members that
// point into shared memory. Alignment will be performed. The
// method returns the physical address pointing just beyond the
// area of shared memory used by E100bexCard.
//
ULONG E100bexCard::SetupSharedMemory(ULONG CbPhys, KNdisSharedMemory& ShMem)
{
if ( !ShMem.IsValid() )
{
ASSERT(ShMem.IsValid());
return CbPhys;
}
// Setup SelfTest Command Block Pointers
PUCHAR pMem = m_Adapter.AlignSharedMemory(&CbPhys, CARD_SHARED_MEM_ALIGNMENT, ShMem);
m_SelfTest = reinterpret_cast<PSELF_TEST_STRUC>(pMem);
m_SelfTestPhys = CbPhys;
CbPhys += sizeof(SELF_TEST_STRUC);
// Setup non-Transmit Command Block Pointers
pMem = m_Adapter.AlignSharedMemory(&CbPhys, CARD_SHARED_MEM_ALIGNMENT, ShMem);
m_NonTxCmdBlock = reinterpret_cast<PNON_TRANSMIT_CB>(pMem);
m_NonTxCmdBlockHdr = reinterpret_cast<PCB_HEADER_STRUC>(pMem);
m_NonTxCmdBlockPhys = CbPhys;
CbPhys += sizeof(NON_TRANSMIT_CB);
// Setup dump buffer area
pMem = m_Adapter.AlignSharedMemory(&CbPhys, CARD_SHARED_MEM_ALIGNMENT, ShMem);
m_DumpSpace = reinterpret_cast<PDUMP_AREA_STRUC>(pMem);
m_DumpSpacePhys = CbPhys;
CbPhys += sizeof(DUMP_AREA_STRUC);
// Setup stats counters area
pMem = m_Adapter.AlignSharedMemory(&CbPhys, CARD_SHARED_MEM_ALIGNMENT, ShMem);
m_StatsCounters = reinterpret_cast<PERR_COUNT_STRUC>(pMem);
m_StatsCounterPhys = CbPhys;
CbPhys += sizeof(ERR_COUNT_STRUC);
TRACE("SelfTest area ptr=%x\n", m_SelfTest);
TRACE("NonTxCmd Block ptr=%x\n", m_NonTxCmdBlock);
TRACE("Dump buffer ptr=%x\n", m_DumpSpace);
TRACE("Stats counts dump area ptr=%x\n", m_StatsCounters);
return CbPhys;
}
////////////////////////////////////////////////////////////////////
// E100bexCard::SetPacketFilter
//
//
// Parameters:
// NewPacketFilter
// IRQL:
//
// Return Mode:
//
// NOTE:
//
NDIS_STATUS E100bexCard::SetPacketFilter(ULONG NewPacketFilter, BOOLEAN bCheckExisting)
{
TRACE("E100bexCard::SetPacketFilter\n");
// Verify bits, if any bits are set that we don't support, leave
if (NewPacketFilter &
~(NDIS_PACKET_TYPE_DIRECTED |
NDIS_PACKET_TYPE_MULTICAST |
NDIS_PACKET_TYPE_BROADCAST |
NDIS_PACKET_TYPE_PROMISCUOUS |
NDIS_PACKET_TYPE_ALL_MULTICAST))
{
TRACE("Filter Type %08x not supported\n", NewPacketFilter);
return NDIS_STATUS_NOT_SUPPORTED;
}
if ( bCheckExisting )
{
// the filtering changes need to result in the hardware being reset.
if (!((NewPacketFilter ^ m_PacketFilter) &
(NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_MULTICAST |
NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_PROMISCUOUS |
NDIS_PACKET_TYPE_ALL_MULTICAST)))
{
TRACE("Filter Type %08x didn't change significantly, so return\n", NewPacketFilter);
// save the new packet filter in our adapter object
m_PacketFilter = NewPacketFilter;
return NDIS_STATUS_SUCCESS;
}
}
// save the new packet filter in our card object
m_PacketFilter = NewPacketFilter;
// Need to enable or disable broadcast and promiscuous support depending
// on the new filter
UCHAR NewParameterField = CB_557_CFIG_DEFAULT_PARM15;
if (NewPacketFilter & NDIS_PACKET_TYPE_BROADCAST)
{
NewParameterField &= ~CB_CFIG_BROADCAST_DIS;
}
else
{
NewParameterField |= CB_CFIG_BROADCAST_DIS;
}
if (NewPacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
{
NewParameterField |= CB_CFIG_PROMISCUOUS;
}
else
{
NewParameterField &= ~CB_CFIG_PROMISCUOUS;
}
NDIS_STATUS Status;
// Only need to do something to the HW if the filter bits have changed.
if ((m_OldParameterField != NewParameterField ) ||
(NewPacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST))
{
TRACE("Filter Type %08x changed -- doing re-config\n", NewPacketFilter);
m_OldParameterField = NewParameterField;
m_NonTxCmdBlockHdr->CbCommand = CB_CONFIGURE;
m_NonTxCmdBlockHdr->CbStatus = 0;
m_NonTxCmdBlockHdr->CbLinkPointer = DRIVER_NULL;
// First fill in the static (end user can't change) config bytes
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[0] = CB_557_CFIG_DEFAULT_PARM0;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[2] = CB_557_CFIG_DEFAULT_PARM2;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[3] = CB_557_CFIG_DEFAULT_PARM3;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[9] = CB_557_CFIG_DEFAULT_PARM9;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[10] = CB_557_CFIG_DEFAULT_PARM10;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[11] = CB_557_CFIG_DEFAULT_PARM11;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[12] = CB_557_CFIG_DEFAULT_PARM12;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[13] = CB_557_CFIG_DEFAULT_PARM13;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[14] = CB_557_CFIG_DEFAULT_PARM14;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[15] = CB_557_CFIG_DEFAULT_PARM15;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[16] = CB_557_CFIG_DEFAULT_PARM16;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[17] = CB_557_CFIG_DEFAULT_PARM17;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[18] = CB_557_CFIG_DEFAULT_PARM18;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[20] = CB_557_CFIG_DEFAULT_PARM20;
// next toggle in or out of promiscuous mode
if (NewPacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
{
// turn on save bad frames
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[6] =
(CB_557_CFIG_DEFAULT_PARM6 | CB_CFIG_SAVE_BAD_FRAMES);
// turn on save short frames
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[7] =
(UCHAR) ((CB_557_CFIG_DEFAULT_PARM7 &
(~(CB_CFIG_URUN_RETRY | CB_CFIG_DISC_SHORT_FRAMES))) |
(m_Ai.AiUnderrunRetry << 1)
);
}
else
{
// turn off save bad frames
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[6] =
CB_557_CFIG_DEFAULT_PARM6;
// turn off save short frames
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[7] =
(UCHAR) ((CB_557_CFIG_DEFAULT_PARM7 &
(~CB_CFIG_URUN_RETRY)) |
(m_Ai.AiUnderrunRetry << 1)
);
}
// Set the Tx and Rx Fifo limits
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[1] =
(UCHAR) ((m_Ai.AiTxFifo << 4) | m_Ai.AiRxFifo);
// set the MWI enable bit if needed
if (m_Ai.MWIEnable)
{
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[3] |= CB_CFIG_B3_MWI_ENABLE;
}
// Set the Tx and Rx DMA maximum byte count fields.
if ((m_Ai.AiRxDmaCount) || (m_Ai.AiTxDmaCount))
{
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[4] = (UCHAR) m_Ai.AiRxDmaCount;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[5] = (UCHAR) (m_Ai.AiTxDmaCount | CB_CFIG_DMBC_EN);
}
else
{
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[4] =
CB_557_CFIG_DEFAULT_PARM4;
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[5] =
CB_557_CFIG_DEFAULT_PARM5;
}
// Setup for MII or 503 operation. The CRS+CDT bit should only be
// set when operating in 503 mode.
if (m_Phy.GetPhyAddress() == 32)
{
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[8] =
(CB_557_CFIG_DEFAULT_PARM8 & (~CB_CFIG_503_MII));
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[15] =
(UCHAR) (NewParameterField | CB_CFIG_CRS_OR_CDT);
}
else
{
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[8] =
(CB_557_CFIG_DEFAULT_PARM8 | CB_CFIG_503_MII);
m_NonTxCmdBlock->NonTxCb.Config.ConfigBytes[15] =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -