📄 interrup.c
字号:
PacketLen = (Adapter->PacketHeader[2]) + ((Adapter->PacketHeader[3])*256) - 4;
PacketLen = (PacketLen < Adapter->MaxLookAhead)?
PacketLen :
Adapter->MaxLookAhead;
//
// Copy up the lookahead data
//
if (!CardCopyUp(Adapter,
Adapter->Lookahead,
Adapter->PacketHeaderLoc,
PacketLen + NE2000_HEADER_SIZE
)) {
//
// Failed! Skip this packet
//
IndicateStatus = SKIPPED;
} else {
//
// Indicate the packet to the wrapper
//
IndicateStatus = Ne2000IndicatePacket(Adapter);
if (IndicateStatus != CARD_BAD) {
Adapter->FramesRcvGood++;
}
}
} else {
//
// Packet is corrupt, skip it.
//
IF_LOUD( DbgPrint("Packet did not pass OK check\n"); )
IndicateStatus = SKIPPED;
}
//
// Handle when the card is unable to indicate good packets
//
if (IndicateStatus == CARD_BAD) {
#if DBG
IF_NE2000DEBUG( NE2000_DEBUG_CARD_BAD ) {
DbgPrint("R: <%x %x %x %x> C %x N %x\n",
Adapter->PacketHeader[0],
Adapter->PacketHeader[1],
Adapter->PacketHeader[2],
Adapter->PacketHeader[3],
Adapter->Current,
Adapter->NicNextPacket);
}
#endif
IF_LOG( Ne2000Log('W');)
//
// Start off with receive interrupts disabled.
//
Adapter->NicInterruptMask = IMR_XMIT | IMR_XMIT_ERR | IMR_OVERFLOW;
//
// Reset the adapter
//
CardReset(Adapter);
//
// Since the adapter was just reset, stop indicating packets.
//
break;
}
//
// (IndicateStatus == SKIPPED) is OK, just move to next packet.
//
if (IndicateStatus == SKIPPED) {
SyncCardGetCurrent((PVOID)Adapter);
Adapter->NicNextPacket = Adapter->Current;
} else {
//
// Free the space used by packet on card.
//
Adapter->NicNextPacket = Adapter->PacketHeader[1];
}
//
// This will set BOUNDARY to one behind NicNextPacket.
//
CardSetBoundary(Adapter);
if (Adapter->ReceivePacketCount > 10) {
//
// Give transmit interrupts a chance
//
Done = FALSE;
Adapter->ReceivePacketCount = 0;
break;
}
}
//
// See if a buffer overflow occured previously.
//
if (Adapter->BufferOverflow) {
//
// ... and set a flag to restart the card after receiving
// a packet.
//
Adapter->BufferOverflow = FALSE;
SyncCardAcknowledgeOverflow(Adapter);
//
// Undo loopback mode
//
CardStart(Adapter);
IF_LOG( Ne2000Log('f'); )
//
// Check if transmission needs to be queued or not
//
if (Adapter->OverflowRestartXmitDpc && Adapter->CurBufXmitting != -1) {
IF_LOUD( DbgPrint("queueing xmit in RcvDpc\n"); )
Adapter->OverflowRestartXmitDpc = FALSE;
Adapter->TransmitInterruptPending = TRUE;
IF_LOG( Ne2000Log('5'); )
CardStartXmit(Adapter);
}
}
//
// Finally, indicate ReceiveComplete to all protocols which received packets
//
if (Adapter->IndicateReceiveDone) {
NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle);
Adapter->IndicateReceiveDone = FALSE;
}
IF_LOUD( DbgPrint( "Ne2000RcvDpc exiting\n" );)
return (Done);
}
VOID
Ne2000XmitDpc(
IN PNE2000_ADAPTER Adapter
)
/*++
Routine Description:
This is the real interrupt handler for a transmit complete interrupt.
Ne2000Dpc queues a call to it.
Called after a transmit complete interrupt. It checks the
status of the transmission, completes the send if needed,
and sees if any more packets are ready to be sent.
Arguments:
Adapter - Pointer to the adapter block.
Return Value:
None.
--*/
{
//
// Packet that was transmitted
//
PNDIS_PACKET Packet;
//
// Status of the send
//
NDIS_STATUS Status;
//
// Length of the packet sent
//
ULONG Len;
//
// Temporary loopnig variable
//
UINT i;
IF_VERY_LOUD( DbgPrint( "Ne2000XmitDpc entered\n" );)
//
// Verify that we are transmitting a packet
//
if ( Adapter->CurBufXmitting == -1 ) {
#if DBG
DbgPrint( "Ne2000HandleXmitComplete called with nothing transmitting!\n" );
#endif
NdisWriteErrorLogEntry(
Adapter->MiniportAdapterHandle,
NDIS_ERROR_CODE_DRIVER_FAILURE,
1,
NE2000_ERRMSG_HANDLE_XMIT_COMPLETE
);
return;
}
IF_LOG( Ne2000Log('C');)
//
// Get the status of the transmit
//
SyncCardGetXmitStatus((PVOID)Adapter);
//
// Statistics
//
if (Adapter->XmitStatus & TSR_XMIT_OK) {
Adapter->FramesXmitGood++;
Status = NDIS_STATUS_SUCCESS;
} else {
Adapter->FramesXmitBad++;
Status = NDIS_STATUS_FAILURE;
}
//
// Mark the current transmit as done.
//
Len = (Adapter->PacketLens[Adapter->CurBufXmitting] + 255) >> 8;
ASSERT (Len != 0);
//
// Free the transmit buffers
//
for (i = Adapter->CurBufXmitting; i < Adapter->CurBufXmitting + Len; i++) {
Adapter->BufferStatus[i] = EMPTY;
}
//
// Set the next buffer to start transmitting.
//
Adapter->NextBufToXmit += Len;
if (Adapter->NextBufToXmit == MAX_XMIT_BUFS) {
Adapter->NextBufToXmit = 0;
}
if (Adapter->BufferStatus[Adapter->NextBufToXmit] == EMPTY &&
Adapter->NextBufToFill != Adapter->NextBufToXmit) {
Adapter->NextBufToXmit = 0;
}
//
// Remove the packet from the outstanding packet list.
//
Packet = Adapter->Packets[Adapter->CurBufXmitting];
Adapter->Packets[Adapter->CurBufXmitting] = (PNDIS_PACKET)NULL;
//
// See what to do next.
//
switch (Adapter->BufferStatus[Adapter->NextBufToXmit]) {
case FULL:
//
// The next packet is ready to go -- only happens with
// more than one transmit buffer.
//
IF_LOUD( DbgPrint( " next packet ready to go\n" );)
//
// Start the transmission and check for more.
//
Adapter->CurBufXmitting = Adapter->NextBufToXmit;
IF_LOG( Ne2000Log('2');)
//
// This is used to check if stopping the chip prevented
// a transmit complete interrupt from coming through (it
// is cleared in the ISR if a transmit DPC is queued).
//
Adapter->TransmitInterruptPending = TRUE;
IF_LOG( Ne2000Log('6'); )
CardStartXmit(Adapter);
break;
case EMPTY:
//
// No packet is ready to transmit.
//
IF_LOUD( DbgPrint( " next packet empty\n" );)
Adapter->CurBufXmitting = (XMIT_BUF)-1;
break;
}
//
// Start next send
//
Ne2000DoNextSend(Adapter);
IF_VERY_LOUD( DbgPrint( "Ne2000XmitDpc exiting\n" );)
}
BOOLEAN
Ne2000PacketOK(
IN PNE2000_ADAPTER Adapter
)
/*++
Routine Description:
Reads a packet off the card -- checking if the CRC is good. This is
a workaround for a bug where bytes in the data portion of the packet
are shifted either left or right by two in some weird 8390 cases.
This routine is a combination of Ne2000TransferData (to copy up data
from the card), CardCalculateCrc and CardCalculatePacketCrc.
Arguments:
Adapter - pointer to the adapter block.
Return Value:
TRUE if the packet seems ok, else false.
--*/
{
//
// Length of the packet
//
UINT PacketLen;
//
// Guess at where the packet is located
//
PUCHAR PacketLoc;
//
// Header Validation Variables
//
BOOLEAN FrameAlign;
PUCHAR PacketRcvStatus;
PUCHAR NextPacket;
PUCHAR PacketLenLo;
PUCHAR PacketLenHi;
PUCHAR ReceiveDestAddrLo;
UINT FrameAlignCount;
UCHAR OldPacketLenHi;
UCHAR TempPacketHeader[6];
PUCHAR BeginPacketHeader;
//
// First copy up the four-byte header the card attaches
// plus first two bytes of the data packet (which contain
// the destination address of the packet). We use the extra
// two bytes in case the packet was shifted right 1 or 2 bytes
//
PacketLoc = Adapter->PageStart +
256*(Adapter->NicNextPacket-Adapter->NicPageStart);
if (!CardCopyUp(Adapter, TempPacketHeader, PacketLoc, 6)) {
return FALSE;
}
PacketLoc += 4;
//
// Validate the header
//
FrameAlignCount = 0;
BeginPacketHeader = TempPacketHeader;
//
// Sometimes the Ne2000 will misplace a packet and shift the
// entire packet and header by a byte, either up by 1 or 2 bytes.
// This loop will look for the packet in the expected place,
// and then shift up in an effort to find the packet.
//
do {
//
// Set where we think the packet is
//
PacketRcvStatus = BeginPacketHeader;
NextPacket = BeginPacketHeader + 1;
PacketLenLo = BeginPacketHeader + 2;
PacketLenHi = BeginPacketHeader + 3;
OldPacketLenHi = *PacketLenHi;
ReceiveDestAddrLo = BeginPacketHeader + 4;
FrameAlign = FALSE;
//
// Check if the status makes sense as is.
//
if (*PacketRcvStatus & 0x05E){
FrameAlign = TRUE;
} else if ((*PacketRcvStatus & RSR_MULTICAST) // If a multicast packet
&& (!FrameAlignCount) // and hasn't been aligned
&& !(*ReceiveDestAddrLo & 1) // and lsb is set on dest addr
){
FrameAlign = TRUE;
} else {
//
// Compare high and low address bytes. If the same, the low
// byte may have been copied into the high byte.
//
if (*PacketLenLo == *PacketLenHi){
//
// Save the old packetlenhi
//
OldPacketLenHi = *PacketLenHi;
//
// Compute new packet length
//
*PacketLenHi = *NextPacket - Adapter->NicNextPacket - 1;
if (*PacketLenHi < 0) {
*PacketLenHi = (Adapter->NicPageStop - Adapter->NicNextPacket) +
(*NextPacket - Adapter->NicPageStart) - 1;
}
if (*PacketLenLo > 0xFC) {
*PacketLenHi++;
}
}
PacketLen = (*PacketLenLo) + ((*PacketLenHi)*256) - 4;
//
// Does it make sense?
//
if ((PacketLen > 1514) || (PacketLen < 60)){
//
// Bad length. Restore the old packetlenhi
//
*PacketLenHi = OldPacketLenHi;
FrameAlign = TRUE;
}
//
// Did we recover the frame?
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -