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

📄 lan91c111_intr.c

📁 This driver was developed to ARM SMSC LAN91C11 (PXA CPU)
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -