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

📄 cs8900.c

📁 zilog z80f91单片机的网络接口函数
💻 C
📖 第 1 页 / 共 2 页
字号:
			#ifdef PB_DEBUG
				OrPortB( 0x10 );
			#endif
			pep = tx_pep_next;
			RZKReleaseSemaphore(g_MacSem);
//			RZKRestorePreemption(CritFlag);
			nic_write( txbuffnext->length, (INT8*)&txbuffnext->dstAddr[0], p_emac_base );
            status = pep->ethPktLen ;   // CR6168 - MSS
		}
		else
		{
			RZKReleaseSemaphore(g_MacSem);
//			RZKRestorePreemption(CritFlag);
		}

	}
	else
	{
		status = PKTTOOBIG;
	}

	return( status );
}

/*----------------------------------------------------------------------------*/
UINT8 no_emac_rx_buffer;



void 
ReceiveEthPkt
(
	EMAC_FRAME_t * 					databuff
)
{	
	no_emac_rx_buffer = 0;
	/*
	 * Rx Data Preceeded by Status (2 bytes) and Length (2 bytes)
	 * Note:  The Status bytes must be read HiLo before reading the 
	 * rest of the data (LoHi) since the CS8900 stores word data in the
	 * opposite endian of the network.
	 *
	 * Even though documentation from Cirrus suggests reading the 
	 * packet length Hi first then Lo, doing this causes truncation of Rx data.
	 * Therefore we go against the spec and read data LoHi.
	 */
	databuff->flags   = DATAPORTH0;
	databuff->flags	= (databuff->flags << 8) + DATAPORTL0;
	databuff->length  = DATAPORT0;

	if( databuff->length )
	{
		nic_read( databuff->length, (INT8*)&databuff->dstAddr[0], p_emac_base );
	}
	else
	{
		printf( "Nothing to read!!!\n" );
	}

#ifdef PERF_TRACE
		kprintf( " M%x ", databuff->Length );
#endif

#if 0
	if( (databuff->flags & 0x304) == 0x304 )
	{
		INT8 *						ptr;
		UINT16							i;

		printf( "Rx Status Flags %x\n", databuff->flags );
		printf( "Rx Length %x\n", databuff->length );
		printf( "Hash = %x\n", MulticastHash( (INT8*)&databuff->dstAddr[0]) );
		printf( "Rx Data: \n");
		ptr = (INT8 *) &databuff->dstAddr[0];	
		for( i=0; i< databuff->length; i++ ) 
		{
			printf( " %x", ptr[i] & 0xFF );
		}	
		printf( "\n" );
	}
#endif
}



/*
 * Internal function to calculate a multicast hash value for the receiver.
 * For this device, a bit mask is used to coarsely filter possible
 * multicast packets.  The bit is calculated by using the CRC algorithm
 * applied to the physical destination address, and then using the six
 * most significant bits as the integer bit index in the eight-byte mask.
 */
static UINT32 crc_poly = 0x04C11DB7;
INT8	
MulticastHash
(
	INT8 * 							addr
)
{
	INT8								HashIndex;
	INT8								AddrByte;
	UINT16								Byte;
	UINT16								Bit;
	INT32 							CRC;

	/*
	 * Compute CRC32 on the 6 byte DA
	 */
	CRC = 0xFFFFFFFF;
	for( Byte=0; Byte<6; Byte++ )
	{
		AddrByte = *addr++;
		for( Bit=0; Bit<8; Bit++, AddrByte>>=1 )
		{
			CRC = (CRC << 1) ^ ( ((CRC < 0) ^ (AddrByte & 1)) ? crc_poly : 0 );
		}
	}

	/*
	 * Hash index is the bottom 6 bits of the CRC in reverse bit order.
	 */
	HashIndex = 0;
	for( Bit=0, HashIndex=0; Bit<6; Bit++ )
	{
		HashIndex = (HashIndex << 1) + ((CRC >> Bit) & 1);
	}

	return( HashIndex );
}



/*
 * Update the hash filter in HW to add another MC address.
 */
void EthMAddFunc
(
	INT8 *							pAddr
)
{
	UINT16             			data;
	UINT16             			bitnum;
	UINT16             			addr;
	UINT16             			saved_PktPage;
	RZK_STATE_t							CritFlag;

/*
kprintf( "Add %02x:%02x:%02x:%02x:%02x:%02x to MC Filter table\n",
		pAddr[0],
		pAddr[1],
		pAddr[2],
		pAddr[3],
		pAddr[4],
		pAddr[5] );
*/

	bitnum = MulticastHash(pAddr);
//	kprintf( "CRC mapping is %x\n", bitnum );

	CritFlag = RZKDisablePreemption();
	saved_PktPage = PKTPAGEPTR;
 	PKTPAGEPTR    = LINECTL;
	PKTPAGEDATA0 &= ~SerRxON;	


	addr   = (LAFILTER + ((bitnum/16)*2));
	bitnum = ( 1 << (bitnum%16) );
	PKTPAGEPTR = addr;
	data       = PKTPAGEDATA0;
//	kprintf( "Read %x from port %x\n", data, addr);
	if( (data & bitnum) == 0 )
	{
		data |= bitnum;
		b_mc_count++;
//		kprintf( "Writing %x to %x\n", data, addr );
	   PKTPAGEDATA0 = data;

//		kprintf( "MC count now %x\n", b_mc_count);

		if( b_mc_count )
		{
			/*
			 * Enable Rx Multicast frames
			 */
			RxFilter 	|= MulticastA;
			PKTPAGEPTR   = RXCTL;
			PKTPAGEDATA0 = (RxFilter | ADDR_RXCTL);
		}
	}

	PKTPAGEPTR    = LINECTL;
	PKTPAGEDATA0 |= SerRxON;
	PKTPAGEPTR 	  = saved_PktPage;

	RZKRestorePreemption(CritFlag);
}



/*
 * Remove given address from the list supported in HW.
 */
void EthMDelFunc
(
	INT8 *							pAddr
)
{
	UINT16             			data;
	UINT16             			bitnum;
	UINT16             			addr;
	UINT16             			saved_PktPage;
	RZK_STATE_t							CritFlag;

/*
kprintf( "Remove %02x:%02x:%02x:%02x:%02x:%02x to MC Filter table\n",
		pAddr[0],
		pAddr[1],
		pAddr[2],
		pAddr[3],
		pAddr[4],
		pAddr[5] );
*/

	bitnum = MulticastHash(pAddr);
//	kprintf( "CRC mapping is %x\n", bitnum );

	CritFlag = RZKDisablePreemption();
	saved_PktPage = PKTPAGEPTR;
 	PKTPAGEPTR    = LINECTL;
	PKTPAGEDATA0 &= ~SerRxON;	


	addr   = (LAFILTER + ((bitnum/16)*2));
	bitnum = ( 1 << (bitnum%16) );
	PKTPAGEPTR = addr;
	data       = PKTPAGEDATA0;
//	kprintf( "Read %x from port %x\n", data, addr);
	if( data & bitnum )
	{
		data &= ~bitnum;
		b_mc_count--;
//		kprintf( "Writing %x to %x\n", data, addr );
	   PKTPAGEDATA0 = data;

//		kprintf( "MC count now %x\n", b_mc_count);

		if( b_mc_count == 0 )
		{
			/*
			 * Disable Rx Multicast frames
			 */
			RxFilter 	&= ~MulticastA;
			PKTPAGEPTR   = RXCTL;
			PKTPAGEDATA0 = (RxFilter | ADDR_RXCTL);
		}
	}
	PKTPAGEPTR    = LINECTL;
	PKTPAGEDATA0 |= SerRxON;
	PKTPAGEPTR 	  = saved_PktPage;

	RZKRestorePreemption(CritFlag);
}




UINT16 emac_save_count = 0;
void cs8900PollTask(void)
{
	UINT32 my_emac_isr_count = 0;
	UINTRMASK intmask ;


	while( 1 )
	{
		RZKSuspendThread( RZKGetCurrentThread(), 100 ) ;    //CR6167 - MSS

		if( my_emac_isr_count == emac_isr_count )
		{
			/*
			 * CS8900A 8-bit interrupt patch:
			 * Simulate a call into the MAC ISR to re-enable interrupts.
			 */
//			emac_save_count++;

			intmask = RZKDisableInterrupts();
			emacisr();
			RZKEnableInterrupts(intmask);
		}
		my_emac_isr_count = emac_isr_count;

	}
}


extern UINT32 SysUpTime;
void CS8900IntTask( void )
{
	UINT16                      i;
	ETH_PKT_t *						pep;
	RZK_STATE_t								CritFlag;
//	RZK_STATUS_t status ;           // Commented during IAR Porting
	UINTRMASK intmask1, intmask2 ;
	
	intmask1 = RZKDisableInterrupts();
	while( 1 )
	{
		i = ISQ;

		while( i )
		{
			RZKEnableInterrupts(intmask1); //changed for debugging
			emac_isr_count++;
#ifdef PERF_TRACE
			kprintf( "ISQ=%x @ %x", i, SysUpTime );
#endif

			switch (i & 0x3F) 	/* lower 6 bits give reg number causing INTR */
			{
				case 0x04:	/* RXEVENT cause ID */
				{
#if 0
					if ((i & BIT_CRCError) && (CRCErrors != 0xFFFF))
						CRCErrors++;
					if ((i & BIT_Runt) && (RuntErrors != 0xFFFF))
						RuntErrors++;
					if ((i & BIT_Extradata) && (ExcessLengthErrors != 0xFFFF))
						ExcessLengthErrors++;
#endif
					if( i & BIT_RXOK )
					{

						RZKAcquireSemaphore(g_MacSem,MAX_INFINITE_SUSPEND);
//						CritFlag = RZKDisablePreemption();
//						b_rx_count++;

						if (rxnotifyfunc != 0)
						{
							no_emac_rx_buffer = 1;
							rxnotifyfunc();
							/*
							 * Check if the ReceivePkt routine was called.  
							 * If it was, no_emac_rx_buffer will be reset to 0.
							 * If it wasn't then the system is out of receive buffers.
							 */
							if(no_emac_rx_buffer)
							{
								volatile INT8	temp;
								volatile INT8 	temp2;
								UINT16	         Len;

								temp  = DATAPORTH0;
								temp2 = DATAPORTL0;
								Len  = DATAPORT0;
								// kprintf( "discarding packet, len is %u\n", Len );
								if( Len )
								{
									nic_discard( Len, p_emac_base );
								}
//								b_rx_count--;
							}
							
						}

//						RZKRestorePreemption(CritFlag);	
						RZKReleaseSemaphore(g_MacSem);
					}

					break;
				}
				case 0x08:	/* TXEVENT cause ID */
				{
					RZKAcquireSemaphore(g_MacSem,MAX_INFINITE_SUSPEND);
//					CritFlag = RZKDisablePreemption();
					doing_tx = RZK_FALSE;
					if( TransmitNextPkt() )
					{
						pep = tx_pep_next;
						nic_write( txbuffnext->length, (INT8*)&txbuffnext->dstAddr[0], p_emac_base );
//						RZKRestorePreemption(CritFlag);
					}
#if 0					
					else
					{
//						RZKRestorePreemption(CritFlag);
						RZKReleaseSemaphore(g_MacSem);
					}
#endif
					RZKReleaseSemaphore(g_MacSem);
					break;
				}
				case 0x0C:	/* BUF EVENT casue ID, space now available for earlier TxCMD request */
				{
					if (i & RDY4TX) 
					{
						#ifdef PB_DEBUG
							OrPortB( 0x04 );
						#endif		
						pep = tx_pep_next;
						nic_write( txbuffnext->length, (INT8*)&txbuffnext->dstAddr[0], p_emac_base );
						#ifdef PB_DEBUG	
							AndPortB( 0xFB );
						#endif		
					};			
					if( i & 0x400 )
					{
//						kprintf( "RxMiss %x\n", ++RxMissCount );
					}

					break;
				}
				case 0x10:	/* RxMiss count overflow */
				{
					if (RxMissCount != 0xFFFF)
						RxMissCount++;	/* Saturating counter */

					break;
				}
				case 0x12:	/* TxCOL count overflow */
				{
					if (TxColCount != 0xFFFF)
						TxColCount++;	/* Saturating counter */

					break;
				}
				default:
				{
					#if DEBUG
					printf("Unexpected CS8900 Interrupt %x\n", i );
					#endif
					break;
				}
			}

			/*
			 * Look for another interrupt
			 */
			intmask1 = RZKDisableInterrupts(); //changed for debugging
			i = ISQ;
		}

		RZKEnableInterrupts(intmask1);

		intmask2 = RZKDisableInterrupts();

		/*
		 * Re-enable CS8900 interrupt generation
		 */
		PKTPAGEPTR    = BUSCTL;
		PKTPAGEDATA0  = ADDR_BUSCTL | ENABLE_IRQ;

		RZKSuspendInterruptThread() ;
		RZKEnableInterrupts(intmask2) ;
	}

}



UINT8
IsEthernetConnected( void )
{
	UINT16    		Save, Data;
	UINT8			Status = RZK_FALSE;
	UINT8			CritFlag;

	CritFlag = RZKDisablePreemption();
	Save 		  = PKTPAGEPTR;
	PKTPAGEPTR = LINEST;
	Data       = PKTPAGEDATA0;
	PKTPAGEPTR = Save;
	RZKRestorePreemption( CritFlag );

	/*
	 * Read the Line Status register to determine if the Link is OK.
	 */
	if( Data & CS8900_LINK_OK )
	{
		Status = RZK_TRUE;
	}

	return( Status );
}

⌨️ 快捷键说明

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