📄 interrup.c
字号:
/****************************************************************************
2004.12 第十项目小组
主编:王翔 徐隽
协助:卢坚 夏亮 傅佳伟 郑皓 黄君炜
测试:王弥
Rtl8139 根据 Win2000 DDK提供的Network Samples框架基础上进行编码
(声明:本驱动程序仅用于学习、探索、实践计算机网络相关知识之用。
请勿在未征得本小组同意的情况下随意传播。对使用本程序可能造成的
硬件问题本小组概不负责。也请勿将它用于学习之外的任何用途,本小组
对此种行为可能造成的不良后果概不负责。)
****************************************************************************/
/****************************************************************************
模块名称:
inturrup.c
模块功能:
处理中断相关的程序,包括收发包
开发环境:
WinDDK XP
Visual C++ 6.0
Driver Studio 3.1
*****************************************************************************/
#define NDIS_WDM 1
#define NDIS_MINIPORT_DRIVER
#define NDIS50_MINIPORT 1 //NDIS版本5.0
#include "ndis.h"
#include "RTL8139sw.h"
#include "RTL8139hw.h"
//
// On debug builds tell the compiler to keep the symbols for
// internal functions, otw throw them out.
//
#if DBG
#define STATIC
#else
#define STATIC static
#endif
INDICATE_STATUS
RTL8139IndicatePacket(
IN PRTL8139_ADAPTER Adapter
);
VOID
RTL8139DoNextSend(
PRTL8139_ADAPTER Adapter
);
//
// This is used to pad short packets.
//
static UCHAR BlankBuffer[60] = " ";
VOID
RTL8139EnableInterrupt(
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
Routine Description:
This routine is used to turn on the interrupt mask.
Arguments:
Context - The adapter for the RTL8139 to start.
Return Value:
None.
--*/
{
PRTL8139_ADAPTER Adapter = (PRTL8139_ADAPTER)(MiniportAdapterContext);
IF_LOG( RTL8139Log('P'); )
CardUnblockInterrupts(Adapter);
}
VOID
RTL8139Isr(
OUT PBOOLEAN InterruptRecognized,
OUT PBOOLEAN QueueDpc,
IN PVOID Context
)
/*++
Routine Description:
This is the interrupt handler which is registered with the operating
system. If several are pending (i.e. transmit complete and receive),
handle them all. Block new interrupts until all pending interrupts
are handled.
Arguments:
InterruptRecognized - Boolean value which returns TRUE if the
ISR recognizes the interrupt as coming from this adapter.
QueueDpc - TRUE if a DPC should be queued.
Context - pointer to the adapter object
Return Value:
None.
--*/
{
PRTL8139_ADAPTER adapter = (PRTL8139_ADAPTER)Context;
USHORT curISR, Tmp;
UCHAR cmd;
NdisRawReadPortUshort(adapter->ioaddr + IntrStatus, &curISR);
NdisRawWritePortUshort(adapter->ioaddr + IntrStatus, curISR);
if(curISR & R39_INTERRUPT_MASK){
NdisRawWritePortUshort(adapter->ioaddr + IntrMask, 0);
adapter->curISR = curISR & R39_INTERRUPT_MASK;
*InterruptRecognized = TRUE;
*QueueDpc = TRUE;
}else{
*InterruptRecognized = FALSE;
*QueueDpc = FALSE;
}
}
VOID
RTL8139HandleInterrupt(
IN NDIS_HANDLE MiniportAdapterContext
)
/*++
Routine Description:
This is the defered processing routine for interrupts. It
reads from the Interrupt Status Register any outstanding
interrupts and handles them.
Arguments:
MiniportAdapterContext - a handle to the adapter block.
Return Value:
NONE.
--*/
{
PRTL8139_ADAPTER adapter = (PRTL8139_ADAPTER)MiniportAdapterContext;
UCHAR TmpTCR;
ULONG Tmplong;
USHORT cur_rx;
USHORT link_changed;
USHORT write_ptr;
if(adapter->curISR & RxUnderrun){
}
//TX
if((adapter->curISR & TxOK)||(adapter->curISR & TxErr)){
TxInterrupt(adapter);
}
//RX
if(adapter->curISR & RxOK){
RxInterrupt(adapter);
}
if( adapter->curISR & (RxErr|RxOverflow|RxFIFOOver)){
//chip write ptr
NdisRawReadPortUshort(adapter->ioaddr + RxBufAddr, &write_ptr);
adapter->read_ptr = write_ptr % RING_BUF_SIZE;
NdisRawWritePortUshort(adapter->ioaddr + RxBufPtr, adapter->read_ptr - 16);
NdisRawWritePortUshort(adapter->ioaddr + IntrStatus, RxOK);
}
//enable interrupt
NdisRawWritePortUshort(adapter->ioaddr + IntrMask, R39_INTERRUPT_MASK);
}
BOOLEAN
RTL8139RcvDpc(
IN PRTL8139_ADAPTER Adapter
)
/*++
Routine Description:
This is the real interrupt handler for receive/overflow interrupt.
Called when a receive interrupt is received. It first indicates
all packets on the card and finally indicates ReceiveComplete().
Arguments:
Adapter - Pointer to the adapter block.
Return Value:
TRUE if done with all receives, else FALSE.
--*/
{
//
// Use to restart a transmit if a buffer overflow occured
// during a transmission
//
BOOLEAN TransmitInterruptWasPending = FALSE;
//
// Status of a received packet.
//
INDICATE_STATUS IndicateStatus = INDICATE_OK;
//
// Flag to tell when the receive process is complete
//
BOOLEAN Done = TRUE;
IF_LOUD( DbgPrint( "RTL8139RcvDpc entered\n" );)
//
// Default to not indicating NdisMEthIndicateReceiveComplete
//
Adapter->IndicateReceiveDone = FALSE;
//
// At this point, receive interrupts are disabled.
//
SyncCardGetCurrent((PVOID)Adapter);
//
// Handle a buffer overflow
//
if (Adapter->BufferOverflow) {
SyncCardHandleOverflow(Adapter);
#if DBG
if (Adapter->OverflowRestartXmitDpc) {
IF_LOG( RTL8139Log('O');)
IF_LOUD( DbgPrint ("Adapter->OverflowRestartXmitDpc set:RcvDpc\n"); )
}
#endif // DBG
}
//
// Loop
//
while (TRUE)
{
if ((Adapter->InterruptStatus & ISR_RCV_ERR) &&
!Adapter->BufferOverflow
)
{
IF_LOUD( DbgPrint ("RCV_ERR, IR=%x\n",Adapter->InterruptStatus); )
//
// Skip this packet
//
SyncCardGetCurrent((PVOID)Adapter);
Adapter->NicNextPacket = Adapter->Current;
CardSetBoundary(Adapter);
break;
}
if (Adapter->Current == Adapter->NicNextPacket) {
//
// Acknowledge previous packet before the check for new ones,
// then read in the Current register.
// The card register Current used to point to
// the end of the packet just received; read
// the new value off the card and see if it
// still does.
//
// This will store the value in Adapter->Current and acknowledge
// the receive interrupt.
//
//
SyncCardGetCurrent((PVOID)Adapter);
if (Adapter->Current == Adapter->NicNextPacket) {
//
// End of Loop -- no more packets
//
break;
}
}
//
// A packet was found on the card, indicate it.
//
Adapter->ReceivePacketCount++;
//
// Verify packet is not corrupt
//
if (RTL8139PacketOK(Adapter)) {
ULONG PacketLen;
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 + RTL8139_HEADER_SIZE
)) {
//
// Failed! Skip this packet
//
IndicateStatus = SKIPPED;
} else {
//
// Indicate the packet to the wrapper
//
IndicateStatus = RTL8139IndicatePacket(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_RTL8139DEBUG( RTL8139_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( RTL8139Log('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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -