?? lan91c111_intr.c
字號:
while (Adapter->AllocPending.First)
{
RetVal = LAN91C111_AdapterAllocBuffer(Adapter, &PacketNumber);
if (STATUS_SUCCESS == RetVal)
{
//So we have some EXTRA memory.. transmit the packet
DequePacket(Adapter->AllocPending, Packet);
pNDISPacket = CONTAINING_RECORD(Packet,NDIS_PACKET,MiniportReserved[0]);
LAN91C111_AdapterWriteData(Adapter, pNDISPacket, PacketNumber);
}
else
{
//Well let's wait for the packet to be allocated
Adapter->AllocIntPending = TRUE;
AllocIntEnabler(Adapter);
break;
}
}
PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111: <== Alloc Interrupt Handler\r\n")));
return;
}
VOID TX_Interrupt_Handler (MINIPORT_ADAPTER *Adapter)
{
ULONG IOBase;
UINT PacketNumber;
USHORT TempWord, PacketStatus;
NDIS_STATUS RetStatus = NDIS_STATUS_SUCCESS;
MINIPORT_PACKET *LocalPkt;
NDIS_PACKET *NdisPacket;
PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111: ==> TX Interrupt Handler\r\n")));
IOBase = Adapter->IOBase;
#ifndef SMSC_AUTO_RELEASE
NdisRawWritePortUshort(IOBase + BANK_SELECT,(USHORT)2);
//Read TXDONE Pkt# from FIFO Port Register
NdisRawReadPortUshort(IOBase + BANK2_FIFOS, &PacketNumber);
PacketNumber &= 0x007F;
//Write to Packet Number Register
NdisRawWritePortUshort(IOBase + BANK2_PNR,(USHORT) PacketNumber);
//Read the Status
NdisRawWritePortUshort(IOBase + BANK2_PTR, (USHORT) (PTR_AUTO | PTR_READ));
NdisStallExecution(1);
NdisRawReadPortUshort(IOBase + BANK2_DATA1, (PUSHORT)&PacketStatus);
//Release the Packet
NdisRawWritePortUshort(IOBase + BANK2_MMU_CMD,(USHORT) CMD_REL_SPEC);
NdisRawReadPortUshort(IOBase + BANK2_MMU_CMD, (PUSHORT) &TempWord);
while (TempWord & MMUCMD_BUSY)
NdisRawReadPortUshort(IOBase + BANK2_MMU_CMD, (PUSHORT) &TempWord);
//Check for errors
if (PacketStatus & TFS_OKAY)
{
RetStatus = NDIS_STATUS_SUCCESS;
//Update statistic counters
Adapter->Stat_TxOK++;
}
else
{
RetStatus = NDIS_STATUS_FAILURE;
Adapter->Stat_TxError++;
}
//Release the packet ownership and return the status
LocalPkt = (MINIPORT_PACKET *) 0;
DequePacket(Adapter->AckPending, LocalPkt);
NdisPacket = CONTAINING_RECORD(LocalPkt,NDIS_PACKET,MiniportReserved[0]);
NdisMSendComplete(Adapter->AdapterHandle, NdisPacket, RetStatus);
#else
//Check for any errors here and release the packet, in case of critical TX error
NdisRawWritePortUshort(IOBase + BANK_SELECT,(USHORT)0);
NdisRawReadPortUshort(IOBase + BANK0_TCR, &TempWord);
if (!(TempWord & TCR_TX_ENA))
{
//Error encountered in TX Clear the packet and set the TXENA
NdisRawWritePortUshort(IOBase + BANK_SELECT,(USHORT)2);
//Read TXDONE Pkt# from FIFO Port Register
NdisRawReadPortUshort(IOBase + BANK2_FIFOS, &PacketNumber);
PacketNumber &= 0x007F;
//Write to Packet Number Register
NdisRawWritePortUshort(IOBase + BANK2_PNR,(USHORT) PacketNumber);
NdisRawWritePortUshort(IOBase + BANK2_MMU_CMD,(USHORT) CMD_REL_SPEC);
NdisRawReadPortUshort(IOBase + BANK2_MMU_CMD, (PUSHORT) &TempWord);
while (TempWord & MMUCMD_BUSY)
NdisRawReadPortUshort(IOBase + BANK2_MMU_CMD, (PUSHORT) &TempWord);
NdisRawWritePortUshort(IOBase + BANK_SELECT,(USHORT)0);
NdisRawWritePortUshort(IOBase + BANK0_TCR, Adapter->TCR);
}
#endif
//Acknowledge the interrupt
NdisRawWritePortUshort(IOBase + BANK_SELECT,(USHORT)2);
NdisRawWritePortUshort(IOBase + BANK2_INT_STS, INT_TX_CMP);
PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111: <== TX Interrupt Handler #%d\r\n"), PacketNumber));
return;
}
VOID RCV_Interrupt_Handler (MINIPORT_ADAPTER *Adapter)
{
ULONG IOBase, DataPort, PtrPort, RxFifoPort, MMUPort;
USHORT FIFO;
USHORT PacketStatus;
USHORT PacketRange, TempRange;
USHORT *ReadBuffer;
MAC_RECEIVE_CONTEXT Context;
int iLength, MaxFrameSize;
UINT iIndex;
SMC_PACK_HEADER *PackHead;
#ifdef SMSC_32BIT_RW
ULONG dFifoData;
USHORT PacketControl;
#else
USHORT dFifoData;
#endif
IOBase = Adapter->IOBase;
DataPort = IOBase + BANK2_DATA1;
PtrPort = IOBase + BANK2_PTR;
RxFifoPort = IOBase + BANK2_RX_FIFO;
MMUPort = IOBase + BANK2_MMU_CMD;
MaxFrameSize = MAX_FRAME_SIZE + ETHERNET_HEADER_SIZE + 4;
PrintDebugMsg(ZONE_RX, (TEXT("LAN91C111: ==> RX Interrupt Handler\r\n")));
//Assume no packet rcvd
Adapter->NeedIndComplete = FALSE;
//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));
NdisStallExecution(1); //Atleast 370ns, so setting to 1us
#ifdef SMSC_32BIT_RW
PackHead = (SMC_PACK_HEADER *) Adapter->LookAheadBuffer;
//Read the first word of the rx area to get the packet status and length
NdisRawReadPortBufferUlong(DataPort,(USHORT *) PackHead,(ULONG)1);
PacketStatus = PackHead->Status;
PacketRange = PackHead->Range;
PrintDebugMsg(ZONE_RX, (TEXT("PacketSts=%04X, PacketRange=%d\r\n"), PacketStatus, PacketRange));
#else
NdisRawReadPortUshort(DataPort, (USHORT *)&dFifoData);
PacketStatus = (USHORT)dFifoData;
NdisRawReadPortUshort(DataPort, (USHORT *)&dFifoData);
PacketRange = (USHORT)dFifoData;
PrintDebugMsg(ZONE_RX, (TEXT("FIFO=%08X, PacketSts=%04X, PacketRange=%d\r\n"), dFifoData, PacketStatus, PacketRange));
#endif
//Check for errors. And discard if bad.
if ((PacketStatus & RFS_ERROR) || (PacketRange > MaxFrameSize) || (PacketRange < MIN_FRAME_SIZE))
{
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;
}
//Good frame received - adjust range for SMSC packet overhead.
PacketRange -= FRAME_OVERHEAD;
ReadBuffer = Adapter->LookAheadBuffer;
#ifdef SMSC_32BIT_RW
iIndex = (PacketRange-1)>>1; //index to the last data
iLength = PacketRange >> 2;
NdisRawReadPortBufferUlong(DataPort, (ULONG *)ReadBuffer, iLength);
NdisRawReadPortUlong(DataPort, (PULONG) &dFifoData);
PrintDebugMsg(ZONE_RX, (TEXT("HW=%04X, LW=%04X\r\n"), HIWORD(dFifoData), LOWORD(dFifoData)));
PrintDebugMsg(ZONE_RX, (TEXT("HB-HW=%02X, LB-HW=%02X, HB-LW=%02X, LB-LW=%02X\r\n"),
HIBYTE(HIWORD(dFifoData)), LOBYTE(HIWORD(dFifoData)), HIBYTE(LOWORD(dFifoData)), LOBYTE(LOWORD(dFifoData))));
//WARNING: This needs to be changed according to the platform's endianess
//HiWord always contains the last word
if (PacketRange % 4)
{
//One extra word
//LoWord contains the Data
//HiWord contains the Control
ReadBuffer[iIndex++] = LOWORD(dFifoData);
PacketControl = HIWORD(dFifoData);
}
else
{
//LoWord contains the Conrol
//HiWord trash
PacketControl = LOWORD(dFifoData);
}
if ((PacketStatus & RFS_ODD) || (Adapter->ChipRev == CHIPREV_LAN91C111_REVA))
{
PacketRange++;
iIndex = (PacketRange-1)>>1; //index to the last data
ReadBuffer[iIndex] = LOBYTE(PacketControl);
PrintDebugMsg(ZONE_RX, (TEXT("Packet Odd Size=%02X, Index=%02X, OddByte=%02X\r\n"), PacketRange, iIndex, LOBYTE(PacketControl)));
}
#else
iLength = PacketRange >> 1;
NdisRawReadPortBufferUshort(DataPort, (USHORT *)ReadBuffer, iLength);
NdisRawReadPortUshort(DataPort, (USHORT *)&dFifoData);
if ((PacketStatus & RFS_ODD) || (Adapter->ChipRev == CHIPREV_LAN91C111_REVA))
{
PacketRange++;
iIndex = (PacketRange-1)>>1; //index to the last data
ReadBuffer[iIndex] = (BYTE)dFifoData;
}
#endif
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((PUSHORT)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;
}
}
}
}
// Release the frame. This acknowledges the interrupt.
NdisRawWritePortUshort(MMUPort,(USHORT) CMD_REM_REL_TOP);
Context.Range = PacketRange;
Context.PacketData = (USHORT *)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);
}
if (Adapter->NeedIndComplete)
NdisMEthIndicateReceiveComplete(Adapter->AdapterHandle);
PrintDebugMsg(ZONE_INTR, (TEXT("LAN91C111: <== RX Interrupt Handler\r\n")));
}
BOOLEAN CheckMultiCastAddress(USHORT *ReadBuffer, MINIPORT_ADAPTER *Adapter)
{
//Start of CheckMultiCastAddress Function definition
UINT Result;
PUCHAR ListEntry;
ULONG Count;
PrintDebugMsg(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;
PrintDebugMsg(ZONE_INIT, (TEXT("LAN91C111: <== CheckMultiCastAddress\r\n")));
}
VOID AllocIntEnabler (MINIPORT_ADAPTER *Adapter)
{
USHORT SavedBS, OldIntReg;
NdisRawReadPortUshort(Adapter->IOBase + BANK_SELECT, &SavedBS);
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,(USHORT) 2);
NdisRawReadPortUshort(Adapter->IOBase + BANK2_INT_STS, &OldIntReg);
OldIntReg &= 0xFF00; //Donot ack
OldIntReg |= INT_ALLOC;
NdisRawWritePortUshort(Adapter->IOBase + BANK2_INT_STS,OldIntReg);
NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT, SavedBS);
return;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -