📄 interrup.c
字号:
Packet = Adapter->Packets[Adapter->CurBufXmitting];
Adapter->Packets[Adapter->CurBufXmitting] = (PNDIS_PACKET)NULL;
SyncCardGetXmitStatus((PVOID)Adapter);
//
// Statistics
//
if (Adapter->XmitStatus & TSR_XMIT_OK) {
Adapter->FramesXmitGood++;
NdisStatus = NDIS_STATUS_SUCCESS;
} else {
Adapter->FramesXmitBad++;
NdisStatus = NDIS_STATUS_FAILURE;
}
for (i = Adapter->CurBufXmitting; i < Adapter->CurBufXmitting + Len; i++) {
Adapter->BufferStatus[i] = EMPTY;
}
Adapter->TransmitInterruptPending = FALSE;
NdisRawWritePortUchar(Adapter->IoAddr+NIC_INTR_STATUS, (ISR_XMIT));
Adapter->CurBufXmitting = Adapter->NextBufToXmit;
Adapter->TransmitInterruptPending = TRUE;
IF_LOG( RTL8139Log('8'); )
Adapter->InterruptStatus &= ~(ISR_XMIT);
CardStartXmit(Adapter);
} else {
NdisRawWritePortUchar(Adapter->IoAddr+NIC_INTR_STATUS, (ISR_XMIT));
Adapter->InterruptStatus |= (Status);
}
}
}
return(NDIS_STATUS_SUCCESS);
}
}
VOID
RTL8139DoNextSend(
PRTL8139_ADAPTER Adapter
)
/*++
Routine Description:
This routine examines if the packet at the head of the packet
list can be copied to the adapter, and does so.
Arguments:
Adapter - Pointer to the adapter block.
Return Value:
None
--*/
{
//
// The packet to process.
//
PNDIS_PACKET Packet;
//
// The current destination transmit buffer.
//
XMIT_BUF TmpBuf1;
//
// Length of the packet
//
ULONG Len;
//
// Temporary looping variable
//
ULONG i;
IF_LOG( RTL8139Log('s'); )
//
// Check if we have enough resources and a packet to process
//
while((Adapter->FirstPacket != NULL) &&
(Adapter->BufferStatus[Adapter->NextBufToFill] == EMPTY)) {
//
// Get the length of the packet.
//
NdisQueryPacket(
Adapter->FirstPacket,
NULL,
NULL,
NULL,
&Len
);
//
// Convert length to the number of transmit buffers needed.
//
Len = (Len + 255) >> 8;
//
// If not transmitting
//
if (Adapter->CurBufXmitting == -1) {
//
// Then check from the next free buffer if the packet will
// fit.
//
if (Adapter->BufferStatus[Adapter->NextBufToXmit] == EMPTY) {
//
// It won't fit at the end, so put it at the first buffer
//
if (Adapter->NextBufToFill + Len > MAX_XMIT_BUFS) {
Adapter->NextBufToFill = 0;
}
} else {
//
// Check if this packet will fit before the packet on the
// adapter.
//
if (Adapter->NextBufToXmit > Adapter->NextBufToFill) {
if (Adapter->NextBufToFill + Len > Adapter->NextBufToXmit) {
IF_LOG( RTL8139Log('^'); )
IF_LOG( RTL8139Log('S'); )
break;
}
} else {
//
// Check if it will fit after the packet already on the
// adapter.
//
if (Adapter->NextBufToFill + Len > MAX_XMIT_BUFS) {
Adapter->NextBufToFill = 0;
if (Adapter->NextBufToFill + Len > Adapter->NextBufToXmit){
IF_LOG( RTL8139Log('%'); )
IF_LOG( RTL8139Log('S'); )
break;
}
}
}
}
} else {
//
// Check if the packet will fit before the packet currently
// transmitting
//
if (Adapter->CurBufXmitting > Adapter->NextBufToFill) {
if (Adapter->NextBufToFill + Len > Adapter->CurBufXmitting) {
IF_LOG( RTL8139Log('$'); )
IF_LOG( RTL8139Log('S'); )
break;
}
} else {
//
// Check if it will fit after the packet currently transmitting
//
if (Adapter->NextBufToFill + Len > MAX_XMIT_BUFS) {
Adapter->NextBufToFill = 0;
if (Adapter->NextBufToFill + Len > Adapter->CurBufXmitting){
IF_LOG( RTL8139Log('!'); )
IF_LOG( RTL8139Log('S'); )
break;
}
}
}
}
//
// Set starting location
//
TmpBuf1 = Adapter->NextBufToFill;
//
// Remove the packet from the queue.
//
Packet = Adapter->FirstPacket;
Adapter->FirstPacket = RESERVED(Packet)->Next;
if (Packet == Adapter->LastPacket) {
Adapter->LastPacket = NULL;
}
//
// Store the packet in the list
//
Adapter->Packets[TmpBuf1] = Packet;
//
// Copy down the packet.
//
if (CardCopyDownPacket(Adapter, Packet,
&Adapter->PacketLens[TmpBuf1]) == FALSE) {
for (i = TmpBuf1; i < TmpBuf1 + Len; i++) {
Adapter->BufferStatus[i] = EMPTY;
}
Adapter->Packets[TmpBuf1] = NULL;
IF_LOG( RTL8139Log('F'); )
IF_LOG( RTL8139Log('S'); )
NdisMSendComplete(
Adapter->MiniportAdapterHandle,
Packet,
NDIS_STATUS_FAILURE
);
continue;
}
//
// Pad short packets with blanks.
//
if (Adapter->PacketLens[TmpBuf1] < 60) {
(VOID)CardCopyDown(
Adapter,
((PUCHAR)Adapter->XmitStart +
TmpBuf1*TX_BUF_SIZE +
Adapter->PacketLens[TmpBuf1]),
BlankBuffer,
60-Adapter->PacketLens[TmpBuf1]
);
}
//
// Set the buffer status
//
for (i = TmpBuf1; i < (TmpBuf1 + Len); i++) {
Adapter->BufferStatus[i] = FULL;
}
//
// Update next free buffer
//
Adapter->NextBufToFill += Len;
if (Adapter->NextBufToFill == MAX_XMIT_BUFS) {
Adapter->NextBufToFill = 0;
}
//
// See whether to start the transmission.
//
if (Adapter->CurBufXmitting == -1) {
//
// OK to start transmission.
//
if (Adapter->BufferStatus[Adapter->NextBufToXmit] == EMPTY &&
Adapter->NextBufToFill != Adapter->NextBufToXmit) {
Adapter->NextBufToXmit = 0;
}
Adapter->CurBufXmitting = Adapter->NextBufToXmit;
IF_LOG( RTL8139Log('4');)
//
// If we are currently handling an overflow, then we need to let
// the overflow handler send this packet...
//
if (Adapter->BufferOverflow) {
Adapter->OverflowRestartXmitDpc = TRUE;
IF_LOG( RTL8139Log('O');)
IF_LOUD( DbgPrint ("Adapter->OverflowRestartXmitDpc set:copy and send");)
} else {
//
// 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('9'); )
CardStartXmit(Adapter);
}
}
//
// Ack the send immediately. If for some reason it
// should fail, the protocol should be able to handle
// the retransmit.
//
IF_LOG( RTL8139Log('S'); )
NdisMSendComplete(
Adapter->MiniportAdapterHandle,
Packet,
NDIS_STATUS_SUCCESS
);
}
}
VOID
OctogmetusceratorRevisited(
IN PRTL8139_ADAPTER Adapter
)
/*++
Routine Description:
Recovers the card from a transmit error.
Arguments:
Adapter - pointer to the adapter block
Return Value:
None.
--*/
{
IF_LOUD( DbgPrint("Octogmetuscerator called!"); )
IF_LOG( RTL8139Log('y'); )
//
// Ack the interrupt, if needed
//
NdisRawWritePortUchar(Adapter->IoAddr+NIC_INTR_STATUS, ISR_XMIT_ERR);
//
// Stop the card
//
SyncCardStop(Adapter);
//
// Wait up to 1.6 milliseconds for any receives to finish
//
NdisStallExecution(2000);
//
// Place the card in Loopback
//
NdisRawWritePortUchar(Adapter->IoAddr+NIC_XMIT_CONFIG, TCR_LOOPBACK);
//
// Start the card in Loopback
//
NdisRawWritePortUchar(Adapter->IoAddr+NIC_COMMAND, CR_START | CR_NO_DMA);
//
// Get out of loopback and start the card
//
CardStart(Adapter);
//
// If there was a packet waiting to get sent, send it.
//
if (Adapter->CurBufXmitting != -1) {
Adapter->TransmitInterruptPending = TRUE;
CardStartXmit(Adapter);
}
IF_LOG( RTL8139Log('Y'); )
}
//中断级别:DISPATCH_LEVEL
VOID
RTL8139SendPackets(
IN NDIS_HANDLE MiniportAdapterContext,
IN PPNDIS_PACKET PacketArray,
IN UINT NumberofPackets
)
/*++
功能描述: 发送数据包
--*/
{
PRTL8139_ADAPTER adapter = (PRTL8139_ADAPTER)MiniportAdapterContext;
UINT i;
for(i = 0; i < NumberofPackets; i ++){
SendPacket(
adapter,
PacketArray[i]
);
}
}
VOID
RTL8139ReturnPacket(
IN NDIS_HANDLE MiniportAdapterContext,
IN PNDIS_PACKET Packet
)
/*++
从上层接受一个包
--*/
{
PRTL8139_ADAPTER adapter = (PRTL8139_ADAPTER)MiniportAdapterContext;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -