📄 interrup.c
字号:
if (Status & (ISR_XMIT)) {
IF_LOG( RTL8029Log('*'); )
//
// Update NextBufToXmit
//
Len = (Adapter->PacketLens[Adapter->CurBufXmitting] + 255) >> 8;
NextBufToXmit = Adapter->NextBufToXmit + Len;
// Adapter->NextBufToXmit += Len;
if (NextBufToXmit == MAX_XMIT_BUFS) {
NextBufToXmit = 0;
}
if (Adapter->BufferStatus[NextBufToXmit] == EMPTY &&
Adapter->NextBufToFill != NextBufToXmit) {
NextBufToXmit = 0;
}
//
// If the next packet is ready to go, start it.
//
if (Adapter->BufferStatus[NextBufToXmit] == FULL) {
//
// Ack the transmit
//
//
// Remove the packet from the packet list.
//
Adapter->NextBufToXmit = NextBufToXmit;
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( RTL8029Log('8'); )
Adapter->InterruptStatus &= ~(ISR_XMIT);
CardStartXmit(Adapter);
} else {
NdisRawWritePortUchar(Adapter->IoAddr+NIC_INTR_STATUS, (ISR_XMIT));
Adapter->InterruptStatus |= (Status);
}
}
}
return(NDIS_STATUS_SUCCESS);
}
}
NDIS_STATUS
RTL8029Send(
IN NDIS_HANDLE MiniportAdapterContext,
IN PNDIS_PACKET Packet,
IN UINT Flags
)
/*++
Routine Description:
The RTL8029Send request instructs a driver to transmit a packet through
the adapter onto the medium.
Arguments:
MiniportAdapterContext - Context registered with the wrapper, really
a pointer to the adapter.
Packet - A pointer to a descriptor for the packet that is to be
transmitted.
SendFlags - Optional send flags
Notes:
This miniport driver will always accept a send. This is because
the RTL8029 has limited send resources and the driver needs packets
to copy to the adapter immediately after a transmit completes in
order to keep the adapter as busy as possible.
This is not required for other adapters, as they have enough
resources to keep the transmitter busy until the wrapper submits
the next packet.
--*/
{
PRTL8029_ADAPTER Adapter = (PRTL8029_ADAPTER)(MiniportAdapterContext);
//
// Put the packet on the send queue.
//
if (Adapter->FirstPacket == NULL) {
Adapter->FirstPacket = Packet;
} else {
RESERVED(Adapter->LastPacket)->Next = Packet;
}
RESERVED(Packet)->Next = NULL;
Adapter->LastPacket = Packet;
//
// Process the next send
//
RTL8029DoNextSend(Adapter);
return(NDIS_STATUS_PENDING);
}
VOID
RTL8029DoNextSend(
PRTL8029_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( RTL8029Log('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( RTL8029Log('^'); )
IF_LOG( RTL8029Log('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( RTL8029Log('%'); )
IF_LOG( RTL8029Log('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( RTL8029Log('$'); )
IF_LOG( RTL8029Log('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( RTL8029Log('!'); )
IF_LOG( RTL8029Log('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( RTL8029Log('F'); )
IF_LOG( RTL8029Log('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( RTL8029Log('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( RTL8029Log('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( RTL8029Log('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( RTL8029Log('S'); )
NdisMSendComplete(
Adapter->MiniportAdapterHandle,
Packet,
NDIS_STATUS_SUCCESS
);
}
}
VOID
OctogmetusceratorRevisited(
IN PRTL8029_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( RTL8029Log('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( RTL8029Log('Y'); )
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -