📄 lan91c111_intr.c
字号:
MINIPORT_PACKET *Packet;
PNDIS_PACKET pNDISPacket;
ULONG IOBase;
NDIS_STATUS RetVal;
PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111: ==> Alloc Interrupt Handler\r\n")));
IOBase = Adapter->IOBase;
Adapter->AllocIntPending = FALSE;
//Get the allocated packet
NdisRawReadPortUshort(IOBase + BANK2_PNR, (PUSHORT)&PacketNumber);
PacketNumber = PacketNumber >> 8; //allocated packet number in higher byte
//Write the allocated packet no. to PNR
NdisRawWritePortUshort(IOBase + BANK2_PNR, PacketNumber);
NdisStallExecution(1);
if (Adapter->AllocPending.First)
{
//Send the packet in the Queue
DequePacket(Adapter->AllocPending, Packet);
pNDISPacket = CONTAINING_RECORD(Packet,NDIS_PACKET,MiniportReserved[0]);
LAN91C111_AdapterWriteData(Adapter, pNDISPacket, PacketNumber);
}
else
{
//Well there is nothing to send, so free this slot
DebugBreak();
NdisRawWritePortUshort(IOBase + BANK2_PNR, PacketNumber);
NdisRawWritePortUshort(IOBase + BANK2_MMU_CMD,(USHORT) CMD_REL_SPEC);
}
//Now check if there are any other packets to send, in the AllocPending queue
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;
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); Adapter->DelQ++;
NdisPacket = CONTAINING_RECORD(LocalPkt,NDIS_PACKET,MiniportReserved[0]);
NdisMSendComplete(Adapter->AdapterHandle, NdisPacket, RetStatus);
//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;
USHORT *ReadBuffer;
USHORT dFifoData;
int iPacketIndex;
PrintDebugMsg(ZONE_RX, (TEXT("LAN91C111: ==> RX Interrupt Handler\r\n")));
IOBase = Adapter->IOBase;
DataPort = IOBase + BANK2_DATA1;
PtrPort = IOBase + BANK2_PTR;
RxFifoPort = IOBase + BANK2_RX_FIFO;
MMUPort = IOBase + BANK2_MMU_CMD;
//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);
iPacketIndex = 0; // initialize Index
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));
// Activate if ARDY is not used
// NdisStallExecution(1); //Atleast 370ns, so setting to 1us
NdisRawReadPortUshort(DataPort, (USHORT *)&dFifoData);
PacketStatus = (USHORT)dFifoData;
NdisRawReadPortUshort(DataPort, (USHORT *)&dFifoData);
PacketRange = (USHORT)dFifoData;
PrintDebugMsg(ZONE_RX, (TEXT("LAN91C111: FIFO=%08X, PacketSts=%04X, PacketRange=%d\r\n"), dFifoData, PacketStatus, PacketRange));
//Check for errors. And discard if bad.
if ((PacketStatus & RFS_ERROR) || (PacketRange > MAX_FRAME_SIZE + FRAME_OVERHEAD) || (PacketRange < MIN_FRAME_SIZE))
{
//Update the counter
if(PacketStatus & RFS_ALIGN)
Adapter->Stat_AlignError++;
Adapter->Stat_RxError++;
//Release the frame. This acknowledges the interrupt.
NdisRawWritePortUshort(MMUPort, (USHORT)CMD_REM_REL_TOP);
//Get ready for next packet
NdisRawReadPortUshort(IOBase + BANK2_FIFOS, &FIFO);
continue;
}
//Good frame received - adjust range for SMSC packet overhead.
PacketRange -= FRAME_OVERHEAD;
ReadBuffer = Adapter->LookAheadBuffer[iPacketIndex];
#ifdef SMSC_32BIT_RW
NdisRawReadPortBufferUlong(DataPort, (ULONG *)ReadBuffer, PacketRange>>2);
NdisRawReadPortUlong(DataPort, (PULONG) &dFifoData);
if (PacketRange % 4)
{
ReadBuffer[(PacketRange-1)>>1] = dFifoData; //index to last data
NdisRawReadPortUshort(DataPort, (PUSHORT)&dFifoData);
}
#else
NdisRawReadPortBufferUshort(DataPort, (USHORT *)ReadBuffer, PacketRange>>1);
NdisRawReadPortUshort(DataPort, (USHORT *)&dFifoData);
#endif
// Odd/Even check
if ((PacketStatus & RFS_ODD) || (Adapter->ChipRev == CHIPREV_LAN91C111_REVA))
{
PacketRange++;
ReadBuffer[(PacketRange-1)>>1] = (BYTE)dFifoData; //index to last data
}
//Release the frame. This acknowledges the interrupt.
NdisRawWritePortUshort(MMUPort, (USHORT)CMD_REM_REL_TOP);
// Address Filter checks
if (Adapter->PromiscuousMode != TRUE)
{
if (PacketStatus & RFS_BCAST)
{
if (Adapter->RCVBroadcast == FALSE)
{
NdisRawReadPortUshort(IOBase + BANK2_FIFOS, &FIFO); //Get ready for next packet
continue;
}
}
else
{
if ((PacketStatus & RFS_MCAST) && (Adapter->RCVAllMulticast == FALSE))
{
//Recv only the mulitcast with the address in the multicast table
if(!CheckMulticastAddress((PUCHAR)ReadBuffer, Adapter))
{
NdisRawReadPortUshort(IOBase + BANK2_FIFOS, &FIFO); //Get ready for next packet
continue;
}
}
}
}
// Adjust buffer length and indicate block of packets, if block is full
// LookAheadBuffer is already mapped into the Packet
NdisAdjustBufferLength(Adapter->Buffer[iPacketIndex], PacketRange);
if (iPacketIndex == MAX_PACKETS-1)
{
NdisMIndicateReceivePacket(Adapter->AdapterHandle, Adapter->Packet, iPacketIndex+1);
iPacketIndex = -1; // reset Index
}
Adapter->NeedIndComplete = TRUE;
//Update the counter
Adapter->Stat_RxOK++;
//Next Frame
NdisRawReadPortUshort( IOBase + BANK2_FIFOS, &FIFO);
iPacketIndex++;
}
// Indicate block of packets, if any
// LookAheadBuffer is already mapped into the Packet
if (iPacketIndex != 0)
{
iPacketIndex--;
NdisMIndicateReceivePacket(Adapter->AdapterHandle, Adapter->Packet, iPacketIndex+1);
}
if (Adapter->NeedIndComplete)
{
//Clear the TX resource pending, since the memory is available
NdisMSendResourcesAvailable(Adapter->AdapterHandle);
}
PrintDebugMsg(ZONE_INTR, (TEXT("LAN91C111: <== RX Interrupt Handler\r\n")));
}
BOOLEAN CheckMulticastAddress(UCHAR *ReadBuffer, MINIPORT_ADAPTER *Adapter)
{
BOOLEAN Result;
PUCHAR ListEntry;
USHORT Count;
PrintDebugMsg(ZONE_RX, (TEXT("LAN91C111: ==> CheckMulticastAddress\r\n")));
ListEntry = Adapter->MulticastTable.MulticastTableEntry;
// 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_EQ(ReadBuffer, ListEntry, &Result);
if (!Result) break; //Found it!
ListEntry += ETH_LENGTH_OF_ADDRESS; //See next entry in multicast list
}
PrintDebugMsg(ZONE_MC, (TEXT("LAN91C111: MCAddr found: %x\r\n"), !Result));
PrintDebugMsg(ZONE_RX, (TEXT("LAN91C111: <== CheckMulticastAddress\r\n")));
return (!Result);
}
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 + -