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

📄 lan91c111_miniport.c

📁 PXA255/270平台的 LAN91C111网卡驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	ULONG                   IOBase;
	UINT                    PacketLength;
	USHORT					PacketNumber;
	NDIS_STATUS			RetVal;
	
	PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111 ==> Miniport Send\r\n")));
	
	IOBase = Adapter->IOBase;
	
	//Make sure that the packet size is in legal limits.
	NdisQueryPacket(pNDISPacket,NULL,NULL,NULL,(PUINT) &PacketLength);
	if ((PacketLength > MAX_FRAME_SIZE) || (PacketLength < MIN_FRAME_SIZE))
	{
		PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111: Invalid Packet Size\r\n")));
		PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111 <== Miniport Send\r\n")));
		return (NDIS_STATUS_FAILURE);
	}
	
	if (Adapter->AllocIntPending)
	{
		PrintDebugMsg(1, (TEXT("LAN91C111: Allocation in process\r\n")));
		PrintDebugMsg(1, (TEXT("LAN91C111: <== Miniport Send\r\n")));        
		Packet			= (MINIPORT_PACKET *) pNDISPacket->MiniportReserved;
		Packet->Next	= (MINIPORT_PACKET *) 0;
		QuePacket(Adapter->AllocPending, Packet);
		Adapter->AllocIntPending = TRUE;
		NdisMSynchronizeWithInterrupt((PNDIS_MINIPORT_INTERRUPT)&Adapter->InterruptInfo, (PVOID)AllocIntEnabler, (PVOID)Adapter);
		return (NDIS_STATUS_PENDING);
	}
	
	RetVal = LAN91C111_AdapterAllocBuffer(Adapter, &PacketNumber);
	if (RetVal == NDIS_STATUS_SUCCESS)
		LAN91C111_AdapterWriteData(Adapter, pNDISPacket, PacketNumber);
	else
	{
		Packet			= (MINIPORT_PACKET *) pNDISPacket->MiniportReserved;
		Packet->Next	= (MINIPORT_PACKET *) 0;
		QuePacket(Adapter->AllocPending, Packet);
		Adapter->AllocIntPending = TRUE;
		NdisMSynchronizeWithInterrupt((PNDIS_MINIPORT_INTERRUPT)&Adapter->InterruptInfo, (PVOID)AllocIntEnabler, (PVOID)Adapter);
		PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111: Allocation FAILED - Packet Queued\r\n")));
		PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111: <== Miniport Send\r\n")));        
		return (NDIS_STATUS_PENDING);
	}
		
	PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111 <== Miniport Send\r\n")));
	return (NDIS_STATUS_PENDING);    
}

/*
Function Name : LAN91C111_MiniportReset
Description   : This function is a required function that issues a hardware reset 
to the network adapter and/or resets the driver抯 software state.
Parameters    : 
PBOOLEAN    AddressingReset -Points to a variable that MiniportReset
sets to TRUE if the NDIS library should call 
MiniportSetInformation to restore addressing information 
to the current values. 
NDIS_HANDLE AdapterContext - Handle to the adapter structure

  Return Value  :
  NDIS_STATUS Status
*/
NDIS_STATUS	LAN91C111_MiniportReset		(
										 PBOOLEAN    AddressingReset,
										 NDIS_HANDLE AdapterContext
										 )
{
	NDIS_STATUS			Status=NDIS_STATUS_SUCCESS;
	MINIPORT_ADAPTER	*Adapter = (MINIPORT_ADAPTER *) AdapterContext;
	USHORT				TempWord;
	ULONG				IOBase;
	INT					Counter;

	PrintDebugMsg(1, (TEXT("LAN91C111 ==> Miniport Reset\r\n")));

	IOBase = Adapter->IOBase;

	//Clear the card's interrupt mask register
	NdisRawWritePortUshort(IOBase + BANK_SELECT, 2);
	NdisRawWritePortUshort(IOBase + BANK2_INT_STS, (USHORT) 0);

	//Just Reset the MMU and clear the Statistics...
	NdisRawWritePortUshort( IOBase + BANK2_MMU_CMD, CMD_RIS);
	NdisRawReadPortUshort(IOBase + BANK2_MMU_CMD, (PUSHORT) &TempWord);
	while (TempWord & MMUCMD_BUSY)
		NdisRawReadPortUshort(IOBase + BANK2_MMU_CMD, (PUSHORT) &TempWord);

	Adapter->State = RESET_STATE;

	//Restore Multicast Hash Table.
	NdisRawWritePortUshort(IOBase + BANK_SELECT, (USHORT) 3);
	for (Counter = 0; Counter < 8; Counter += 2)
		NdisRawWritePortUshort(IOBase + BANK3_MT01 + Counter, *(USHORT*)(&Adapter->HashTable[Counter]));

	//Setup Receive control Register
	Adapter->RCVAllMulticast = TRUE;
	Adapter->RCVBroadcast = TRUE;
	Adapter->PromiscuousMode = FALSE;
	Adapter->RCR = 0;
	Adapter->RCR |= RCR_STRP_CRC;
	Adapter->RCR |= RCR_RX_EN;
	Adapter->RCR |= RCR_ALL_MUL;
	NdisRawWritePortUshort( IOBase + BANK_SELECT, (USHORT) 0);
	NdisRawWritePortUshort(IOBase + BANK0_RCR, Adapter->RCR);

	//Clear all the statistic counter
	Adapter->Stat_RxError		=
		Adapter->Stat_RxOK		=
		Adapter->Stat_RxOvrn	=
		Adapter->Stat_TxError	=
		Adapter->Stat_TxOK		= 
		Adapter->Stat_AlignError =
		Adapter->Stat_MultiColl = 
		Adapter->Stat_SingleColl = 0;

	//Initialize Queues.
	ClearPacketQue(Adapter->AckPending); Adapter->DelQ = Adapter->AddQ = 0;
	ClearPacketQue(Adapter->AllocPending);
	Adapter->AllocIntPending = FALSE;

		//Setup Transmit Control Register
	Adapter->TCR = (USHORT)(TCR_TX_ENA | TCR_PAD_EN | TCR_MON_CSN);
	if (Adapter->Duplex == FULL_DUPLEX)
		Adapter->TCR |= TCR_SWFDUP;
	NdisRawWritePortUshort(IOBase+BANK_SELECT, (USHORT) 0);
	NdisRawWritePortUshort( IOBase + BANK0_TCR, Adapter->TCR);

	//Enable the interrupts !!
	NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,(USHORT) 2);
	NdisRawWritePortUshort( Adapter->IOBase + BANK2_INT_STS,(USHORT)(ENABLED_INTS << 8));

	Adapter->State = NORMAL_STATE;

	PrintDebugMsg(ZONE_INIT, (TEXT("LAN91C111 <== Miniport Reset\r\n")));
	return Status;
}

/*
Function Name : LAN91C111_AdapterAllocBuffer
Description   : Allocates a buffer for TX pacet. The PacketNumber holds the packet allocated.
Return Value  : NDIS_STAUS_SUCCESS if allocation is success
				NDIS_STATUS_FAILURE if allocation failed, in this case PacketNumber is invalid
*/
NDIS_STATUS LAN91C111_AdapterAllocBuffer(MINIPORT_ADAPTER *Adapter, USHORT *PacketNumber)
{
	ULONG				IOBase;
	UINT				AllocateOk;     
	USHORT				AllocSts;
		
	*PacketNumber = -1;
	IOBase = Adapter->IOBase;

	//Allocate memory
	NdisRawWritePortUshort(IOBase + BANK_SELECT,2);
	NdisRawWritePortUshort(IOBase + BANK2_MMU_CMD,(USHORT)(CMD_ALLOC));
	AllocateOk = MMU_WAIT;
	while(AllocateOk)
	{
		NdisRawReadPortUshort(IOBase + BANK2_INT_STS, (PUSHORT) &AllocSts);
		if(AllocSts & INT_ALLOC) break;
		AllocateOk--;
	}
	
	if (!(AllocSts & INT_ALLOC))
		return (NDIS_STATUS_FAILURE);
	else
	{
		NdisRawReadPortUshort(IOBase + BANK2_PNR, PacketNumber);
		*PacketNumber = *PacketNumber >> 8; //allocated packet number in higher byte
		PrintDebugMsg(ZONE_TX, (TEXT("\tLAN91C111: Packet #%d Allocated\r\n"), *PacketNumber));
		return (NDIS_STATUS_SUCCESS);
	}	
}

NDIS_STATUS LAN91C111_AdapterWriteData(
							 MINIPORT_ADAPTER *Adapter,
							 PNDIS_PACKET pNDISPacket,
							 UINT         PacketNumber
							 )
{
	PNDIS_BUFFER            pCurrentBuffer;
	ULONG                   IOBase;
	UINT                    PacketLength,
		CurrentBufferLength;
	PUCHAR              pCurrentBufferAddr,
		ptemp;
	UCHAR               OddByte=0;
	MINIPORT_PACKET     *Packet;
	USHORT              ControlWord;
			
	PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111 ==> AdapterWriteData\r\n")));
	
	IOBase = Adapter->IOBase;
	
	//Make sure that the packet size is in legal limits.
	NdisQueryPacket(pNDISPacket,NULL,NULL,&pCurrentBuffer,(PUINT) &PacketLength);
	
	NdisRawWritePortUshort(IOBase + BANK_SELECT,2);
	//Write the allocated packet no. to PNR
	NdisRawWritePortUshort(IOBase + BANK2_PNR, PacketNumber);
	NdisStallExecution(1);
	
	//Set the pointer register to TX + AUTO_INCR + WRITE
	NdisRawWritePortUshort(IOBase + BANK2_PTR, PTR_AUTO);
	NdisStallExecution(1); //Wait for 1us (as per the Data sheet atleast 370ns)
	
	//Write the status word (placeholder)
	NdisRawWritePortUshort(IOBase + BANK2_DATA1, (USHORT) 0);
	
	//Write the byte count + packet overhead
	NdisRawWritePortUshort(IOBase + BANK2_DATA1, (USHORT)(PacketLength+FRAME_OVERHEAD));
	
	//Query for the first non-zero buffer
	NdisQueryPacket(pNDISPacket,NULL,NULL,&pCurrentBuffer,(PUINT) &PacketLength);
	NdisQueryBuffer(pCurrentBuffer, (PVOID*)&pCurrentBufferAddr, &CurrentBufferLength);
	while ((pCurrentBuffer) && (CurrentBufferLength == 0))
	{
		NdisGetNextBuffer(pCurrentBuffer, (PNDIS_BUFFER *)&pCurrentBuffer);
		NdisQueryBuffer(pCurrentBuffer, (PVOID*)&pCurrentBufferAddr, &CurrentBufferLength);
	}
	
	//Copy the data to the TxBuffer   
	ptemp = Adapter->TxBuffer;
	do
	{
		NdisMoveMemory(ptemp, pCurrentBufferAddr, (ULONG)CurrentBufferLength);
		(ULONG)ptemp += CurrentBufferLength;
		NdisGetNextBuffer (pCurrentBuffer, (PNDIS_BUFFER *)&pCurrentBuffer);  //Get the next buffer
		if (pCurrentBuffer != NULL)
			NdisQueryBuffer (pCurrentBuffer, (PVOID*)&pCurrentBufferAddr, &CurrentBufferLength);        
	}
	while(pCurrentBuffer);

#ifdef SMSC_32BIT_RW
	{
		NdisRawWritePortBufferUlong(IOBase + BANK2_DATA1, Adapter->TxBuffer, PacketLength>>2);
		if ((PacketLength & 0xFFFE) % 4)
		{
			USHORT LastWord;
			if (PacketLength & 1)
				LastWord = *((PUSHORT)(Adapter->TxBuffer+PacketLength-3));
			else
				LastWord = *((PUSHORT)(Adapter->TxBuffer+PacketLength-2));
			NdisRawWritePortUshort(IOBase + BANK2_DATA1, LastWord);
		}
	}
#else
	//Write the data to the chip
	NdisRawWritePortBufferUshort(IOBase + BANK2_DATA1, Adapter->TxBuffer, PacketLength>>1);
#endif
	
	//If odd length packet
	if (PacketLength & 1)
	{
		ptemp = Adapter->TxBuffer;
		OddByte = ptemp[PacketLength-1];
		ControlWord = ((CTL_BYTE_ODD | CTL_BYTE_CRC) << 8)| OddByte;
	}
	else
		ControlWord = (CTL_BYTE_CRC<< 8);
	//Write the control word to the chip
	NdisRawWritePortUshort(IOBase+BANK2_DATA1, (USHORT)ControlWord);
    
	//Now enque the packet for transmission..
	NdisRawWritePortUshort( IOBase + BANK_SELECT, (USHORT) 2);
	NdisRawWritePortUshort (IOBase+BANK2_MMU_CMD, CMD_ENQ_TX);   
	
	Packet			= (MINIPORT_PACKET *) pNDISPacket->MiniportReserved;
	Packet->Next	= (MINIPORT_PACKET *) 0;
	QuePacket(Adapter->AckPending, Packet); Adapter->AddQ++;
	PrintDebugMsg(ZONE_TX, (TEXT("LAN91C111 <== AdapterWriteData\r\n")));
	return (NDIS_STATUS_PENDING);
}

BOOLEAN LAN91C111_MiniportCheckforHang(
									   NDIS_HANDLE AdapterContext
									   )
{
	MINIPORT_ADAPTER        *Adapter = (MINIPORT_ADAPTER *) AdapterContext;
	ULONG IOBase;
	USHORT FIFO, MIR;
	BOOLEAN RetVal = FALSE;
	IOBase = Adapter->IOBase;
	
	NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,2);
	NdisRawReadPortUshort(Adapter->IOBase + BANK2_FIFOS, &FIFO);
	NdisRawWritePortUshort(Adapter->IOBase + BANK_SELECT,(USHORT) 0);
	NdisRawReadPortUshort(Adapter->IOBase + BANK0_MIR, &MIR);
	
	if ((!(Adapter->AckPending.First)) && (Adapter->AllocIntPending == FALSE))
	{
		//If Nothing in TX and RX
		//and atleast one slot is used, then reset.
		if (((MIR & 0xFF00) != 0x0400) && (FIFO & 0x8000))
			RetVal = TRUE;
	}
	return RetVal;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -