📄 interrup.c
字号:
// a packet.
//
Adapter->BufferOverflow = FALSE;
SyncCardAcknowledgeOverflow(Adapter);
//
// Undo loopback mode
//
CardStart(Adapter);
IF_LOG( RTL8139Log('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( RTL8139Log('5'); )
CardStartXmit(Adapter);
}
}
//
// Finally, indicate ReceiveComplete to all protocols which received packets
//
if (Adapter->IndicateReceiveDone) {
NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle);
Adapter->IndicateReceiveDone = FALSE;
}
IF_LOUD( DbgPrint( "RTL8139RcvDpc exiting\n" );)
return (Done);
}
VOID
RTL8139XmitDpc(
IN PRTL8139_ADAPTER Adapter
)
/*++
Routine Description:
This is the real interrupt handler for a transmit complete interrupt.
RTL8139Dpc 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( "RTL8139XmitDpc entered\n" );)
//
// Verify that we are transmitting a packet
//
if ( Adapter->CurBufXmitting == -1 ) {
#if DBG
DbgPrint( "RTL8139HandleXmitComplete called with nothing transmitting!\n" );
#endif
NdisWriteErrorLogEntry(
Adapter->MiniportAdapterHandle,
NDIS_ERROR_CODE_DRIVER_FAILURE,
1,
RTL8139_ERRMSG_HANDLE_XMIT_COMPLETE
);
return;
}
IF_LOG( RTL8139Log('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( RTL8139Log('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( RTL8139Log('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
//
RTL8139DoNextSend(Adapter);
IF_VERY_LOUD( DbgPrint( "RTL8139XmitDpc exiting\n" );)
}
BOOLEAN
RTL8139PacketOK(
IN PRTL8139_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 RTL8139TransferData (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 RTL8139 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?
//
if (!FrameAlign && ((*NextPacket < Adapter->NicPageStart) ||
(*NextPacket > Adapter->NicPageStop))) {
IF_LOUD( DbgPrint ("Packet address invalid in HeaderValidation\n"); )
FrameAlign = TRUE;
}
}
//
// FrameAlignment - if first time through, shift packetheader right 1 or 2 bytes.
// If second time through, shift it back to where it was and let it through.
// This compensates for a known bug in the 8390D chip.
//
if (FrameAlign){
switch (FrameAlignCount){
case 0:
BeginPacketHeader++;
PacketLoc++;
if (!Adapter->EightBitSlot){
BeginPacketHeader++;
PacketLoc++;
}
break;
case 1:
BeginPacketHeader--;
PacketLoc--;
if (!Adapter->EightBitSlot){
BeginPacketHeader--;
PacketLoc--;
}
break;
}
FrameAlignCount++;
}
} while ( (FrameAlignCount < 2) && FrameAlign );
//
// Now grab the packet header information
//
Adapter->PacketHeader[0] = *BeginPacketHeader;
BeginPacketHeader++;
Adapter->PacketHeader[1] = *BeginPacketHeader;
BeginPacketHeader++;
Adapter->PacketHeader[2] = *BeginPacketHeader;
BeginPacketHeader++;
Adapter->PacketHeader[3] = *BeginPacketHeader;
//
// Packet length is in bytes 3 and 4 of the header.
//
Adapter->PacketHeaderLoc = PacketLoc;
PacketLen = (Adapter->PacketHeader[2]) + ((Adapter->PacketHeader[3])*256) - 4;
//
// Sanity check the packet
//
if ((PacketLen > 1514) || (PacketLen < 60)){
if ((Adapter->PacketHeader[1] < Adapter->NicPageStart) ||
(Adapter->PacketHeader[1] > Adapter->NicPageStop)) {
//
// Return TRUE here since IndicatePacket will notice the error
// and handle it correctly.
//
return(TRUE);
}
return(FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -