⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lan91c111_intr.c

📁 PXA255/270平台的 LAN91C111网卡驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -