📄 lan91c111_intr.c
字号:
//Process the waiting packet.
if(Adapter->AllocPending.First)
DequePacket(Adapter->AllocPending, Packet);
if(Packet)
{
Packet->PacketNumber = PacketNumber;
AdapterWrite(Adapter, Packet);
}
else
{
NdisRawWritePortUchar(IOBase + BANK2_PNR,PacketNumber);
NdisRawWritePortUshort(IOBase,(USHORT) CMD_REL_SPEC);
}
while(Adapter->AllocPending.First)
{
if(!AllocateTxBuffer(Adapter, (MINIPORT_PACKET **) &Packet))
break;
else
AdapterWrite(Adapter, Packet);
}
DEBUGMSG(ZONE_INIT, (TEXT("LAN91C111: <== ALLOC Interrupt Handler\r\n")));
}
VOID TX_Interrupt_Handler (MINIPORT_ADAPTER *Adapter)
{
UINT IOBase;
UCHAR SavedPnr,
PacketNumber;
USHORT PacketStatus,
PacketRange,
Pointer,
TempWord,
Count = PTR_WAIT;
MINIPORT_PACKET *LocalPkt;
NDIS_PACKET *NdisPacket;
NDIS_STATUS TransmitStatus = NDIS_STATUS_SUCCESS;
RETAILMSG(ZONE_INIT, (TEXT("LAN91C111: ==> TX Interrupt Handler\r\n")));
IOBase = Adapter->IOBase;
Adapter->XmitPending--;
//Save the Packet Number Register, for restoring later
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,2);
NdisRawReadPortUshort(IOBase + BANK2_PNR, &TempWord);
SavedPnr = LOBYTE(TempWord);
//Read TXDONE Pkt# from FIFO Port Register
NdisRawReadPortUshort( IOBase + BANK2_FIFOS, &TempWord );
PacketNumber = (CHAR)LOBYTE(TempWord);
//Write to Packet Number Register
NdisRawWritePortUshort(IOBase + BANK2_PNR,(USHORT) PacketNumber);
//Retrieve packet status and range
NdisRawWritePortUshort(IOBase + BANK2_PTR, (USHORT) (PTR_AUTO | PTR_READ));
while(Count--)
NdisRawReadPortUshort(IOBase + BANK2_PTR,(PUSHORT) &Pointer);
NdisRawReadPortUshort(IOBase + BANK2_DATA1, (PUSHORT) &PacketStatus);
NdisRawReadPortUshort(IOBase + BANK2_DATA1, (PUSHORT) &PacketRange);
RETAILMSG(ZONE_INIT, (TEXT("LAN91C111: ==> PacketStatus=%X\r\n"),PacketStatus));
RETAILMSG(ZONE_INIT, (TEXT("LAN91C111: ==> PacketRange=%X\r\n"),PacketRange));
//Release the Packet
NdisRawWritePortUshort(IOBase + BANK2_MMU_CMD, (USHORT) CMD_REL_SPEC);
//Acknowledge the interrupt
NdisRawWritePortUshort(IOBase + BANK2_INT_STS, INT_TX_CMP);
if (PacketStatus & TFS_ERROR)
{
TransmitStatus = NDIS_STATUS_FAILURE;
Adapter->Stat_TxError++;
}
else
Adapter->Stat_TxOK++;
if(PacketStatus & TFS_MULTICOL)
Adapter->Stat_MultiColl++;
if(PacketStatus & TFS_1COL)
Adapter->Stat_SingleColl++;
LocalPkt = (MINIPORT_PACKET *) 0;
if (Adapter->AckPending.First)
{
Adapter->TransmitQueueDepth --;
DequePacket(Adapter->AckPending, LocalPkt);
NdisPacket = CONTAINING_RECORD(LocalPkt,NDIS_PACKET,MiniportReserved[0]);
//NdisMSendComplete(Adapter->AdapterHandle,NdisPacket,TransmitStatus);
}
NdisRawWritePortUshort(IOBase + BANK2_PNR, (USHORT)SavedPnr);
RETAILMSG(ZONE_INIT, (TEXT("LAN91C111: <== TX Interrupt Handler\r\n")));
return;
}
VOID RCV_Interrupt_Handler (MINIPORT_ADAPTER *Adapter)
{
UINT IOBase, DataPort, PtrPort, RxFifoPort, MMUPort;
USHORT FIFO;
USHORT PacketStatus;
USHORT PacketRange, TempRange;
UCHAR *ReadBuffer;
MAC_RECEIVE_CONTEXT Context;
SMC_PACK_HEADER *PackHead;
RETAILMSG(1, (TEXT("LAN91C111: <==>RX Interrupt\r\n")));
DEBUGMSG(ZONE_INIT, (TEXT("LAN91C111: ==> RCV Interrupt Handler\r\n")));
IOBase = Adapter->IOBase;
DataPort = IOBase + BANK2_DATA1;
PtrPort = IOBase + BANK2_PTR;
RxFifoPort = IOBase + BANK2_RX_FIFO;
MMUPort = IOBase;
//Check the fifo for the packets to be recvd
NdisRawWritePortUshort(IOBase + BANK_SELECT,(USHORT)2);
NdisRawReadPortUshort(IOBase + BANK2_FIFOS, &FIFO);
while(!(FIFO & FIFO_RX_EMPTY))
{
//Set the pointer to Recieve Area, Auto Increment and Read mode
NdisRawWritePortUshort(PtrPort, (USHORT) (PTR_RCV | PTR_AUTO | PTR_READ));
PackHead = (SMC_PACK_HEADER *) Adapter->LookAheadBuffer;
//Read the first word of the rx area to get the packet status and length
NdisRawReadPortBufferUshort(DataPort,(USHORT *) PackHead,(ULONG)2);
PacketStatus = PackHead->Status;
PacketRange = PackHead->Range;
//Check for errors. And discard if bad.
if (PacketStatus & RFS_ERROR)
{
if(PacketStatus & RFS_ALIGN)
Adapter->Stat_AlignError++;
//Release the frame. This acknowledges the interrupt.
NdisRawWritePortUshort(MMUPort, (USHORT) CMD_REM_REL_TOP);
//Update the counter
Adapter->Stat_RxError++;
//Get ready for the next packet
NdisRawReadPortUshort( IOBase + BANK2_FIFOS, &FIFO);
continue;
}
if (Adapter->PromiscuousMode != TRUE)
{
if (PacketStatus & RFS_BCAST)
{
if (Adapter->RCVBroadcast == FALSE)
{
//Release the frame. This acknowledges the interrupt.
NdisRawWritePortUshort(MMUPort, (USHORT) CMD_REM_REL_TOP);
//Get ready for the next packet
NdisRawReadPortUshort( IOBase + BANK2_FIFOS, &FIFO);
continue;
}
}
else
{
if ((PacketStatus & RFS_MCAST) && (Adapter->RCVAllMulticast == FALSE))
{
//Recv only the mulitcast with the address in the multicast table
if(!CheckMultiCastAddress(ReadBuffer,Adapter))
{
//Release the frame. This acknowledges the interrupt.
NdisRawWritePortUshort(MMUPort, (USHORT) CMD_REM_REL_TOP);
//Get ready for the next packet
NdisRawReadPortUshort( IOBase + BANK2_FIFOS, &FIFO);
continue;
}
}
}
}
//Good frame received - adjust range for SMSC packet overhead.
PacketRange -= FRAME_OVERHEAD;
if ((Adapter->ChipID == CHIPID_LAN91C111) && (Adapter->ChipRev == CHIPREV_LAN91C111_REVA))
{
//LAN91C111 RevA doesn't set the odd-frame bit in recv status
//To fix this just increment the frame size by 1 and
//Let the higher layer figure it out
PacketRange++;
}
else
{
if (PacketStatus & RFS_ODD)
PacketRange++;
}
ReadBuffer = Adapter->LookAheadBuffer;
NdisRawReadPortBufferUshort(DataPort,(ULONG *) ReadBuffer,PacketRange>>1);
if (PacketRange & 0x01)
NdisRawReadPortUchar(DataPort,&ReadBuffer[PacketRange-1]);
// Release the frame. This acknowledges the interrupt.
NdisRawWritePortUshort(MMUPort,(USHORT) CMD_REM_REL_TOP);
Context.Range = PacketRange;
Context.PacketData = ReadBuffer;
TempRange = PacketRange - ETHERNET_HEADER_SIZE;
//Indicate the frame
NdisMEthIndicateReceive(Adapter->AdapterHandle,
(NDIS_HANDLE) &Context,
(void *) ReadBuffer,
(UINT) ETHERNET_HEADER_SIZE,
(void *) ((char *) ReadBuffer + ETHERNET_HEADER_SIZE),
TempRange,
TempRange);
Adapter->NeedIndComplete = TRUE;
//Update the counter
Adapter->Stat_RxOK++;
//Next Frame
NdisRawReadPortUshort( IOBase + BANK2_FIFOS, &FIFO);
}
DEBUGMSG(ZONE_INIT, (TEXT("LAN91C111: <== RCV Interrupt Handler\r\n")));
}
BOOLEAN CheckMultiCastAddress(UCHAR *ReadBuffer, MINIPORT_ADAPTER *Adapter)
{
//Start of CheckMultiCastAddress Function definition
UINT Result;
PUCHAR ListEntry;
ULONG Count;
DEBUGMSG(ZONE_INIT, (TEXT("LAN91C111: ==> CheckMultiCastAddress\r\n")));
Result = 1;
Count = 0;
ListEntry = Adapter->MulticastTable.MulticastTableEntry;
//If empty list then get out.
if(Adapter->MulticastTable.MulticastTableEntryCount == 0)
return FALSE;
// checking all the multicasttable entries against frame address.
for(Count = 0; Count <Adapter->MulticastTable.MulticastTableEntryCount; Count++)
{
// Compare the Ethernet Frame Address with MulticastTableList
ETH_COMPARE_NETWORK_ADDRESSES(ReadBuffer, ListEntry, &Result);
if(!Result) break;
ListEntry += 6;//See next entry in multicast list
}
//returning the value depending upon the MultiCastTableCount.
//If Less than TotalCount return TRUE means finds some multicast address
// same as frame adress
if(Count <= Adapter->MulticastTable.MulticastTableEntryCount)
return TRUE;
else
return FALSE;
DEBUGMSG(ZONE_INIT, (TEXT("LAN91C111: <== CheckMultiCastAddress\r\n")));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -