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

📄 driver.c

📁 mcf5307实验源代码
💻 C
📖 第 1 页 / 共 4 页
字号:

	// length is destined to be even.
	// and of cource, the packet should bigger than 
	// 64 bytes.

	tempss = length << 1;
	if ( tempss < 60 )
		tempss = 60;
	outportb( TBCR0ADD, tempss % 256 );
	outportb( TBCR1ADD, tempss / 256 );

	PacketDelivered = 0;
	STARTTRANSMIT

	// This is also very important, as if we enable interrupt here
	// and in interrupt service, there destined to be a "SETTOPAGE0".
	// refer to SETTOPAGE0, read CR out(TXP bit still exist), then
	// write CR in( now TXP don't exist), dual-transmition occur!!! 
	i = 0;
	while( 1 )
	{
		regtemp = inportb( CRADD );
		if ( !(regtemp & 0x04) )
			break;
		wait(1);
		if ( i++ > NET_TMO_TMIT )
			break;
	}
	if ( i > NET_TMO_TMIT )
	{
		//NU_Control_Interrupts( pre_int_lev );  
		ENABLENETINTERRUPT
		NU_Change_Preemption( NU_PREEMPT );
		return ( NET_ERROR_TRANSBLOCK );
	}

	// first of all, open interrupt to make sure we
	// can receive now.
	//NU_Control_Interrupts( pre_int_lev );  
			
	// See if we get the packet delivered, if it is not delivered,
	// just wait for a while, and when we are waiting, other 
	// tasks who should call "TransmitAPacket" will not be allowed.
	// Attention!!! transmit interrupt may happen here, in this case,
	// we will not get ISR set in the following lines, so, we use 
	// "PacketDelivered" to help us out.
	i = 0;
	while( 1 )
	{
		// No need to SETTOPAGE0 and mask interrupt, as in interrupt service, 
		// after each time of "SETTOPAGE1", there is a "SETTOPAGE0".
		regtemp = inportb( ISRADD );
		if ( ( regtemp & 0x08 ) || ( regtemp & 0x02 ) || ( 1 == PacketDelivered ) )
		{
			outportb( ISRADD, 0x0a );
			break;
		}
		wait(1);
		if ( i++ > NET_TMO_TMIT )
			break;
	}
	
	ENABLENETINTERRUPT
	NU_Change_Preemption( NU_PREEMPT );
	// NU_Change_Preemption( NU_PREEMPT );
	if ( i > NET_TMO_TMIT )
		return( NET_ERROR_TRANSBLOCK );
	else 
		return( NET_NO_ERROR );

}


/****************************************************************************/
/* FUNCTION                                                                 */
/*                                                                          */
/*    NU_Xmit_Packet                                                        */
/*                                                                          */
/* DESCRIPTION                                                              */
/*                                                                          */
/*    This function will handle placing the passed in packet onto the actual*/
/*    wire.  This routine will make sure that each packet is at least 60    */
/*    bytes long.                                                           */
/*                                                                          */
/* CALLED BY                                                                */
/*                                                                          */
/*    dlayersend in net.c file                                              */
/*                                                                          */
/* CALLS                                                                    */
/*                                                                          */
/*                                                                          */
/* INPUTS                                                                   */
/*                                                                          */
/*    uchar    : pointer to the packet which is to be sent over the wire.   */
/*    sshort   : number of schar's which will be sent total.                */
/*                                                                          */
/* OUTPUTS                                                                  */
/*                                                                          */
/*    sshort   : Returns NU_FALSE (0) if ok, else -1 due to wait for trans  */
/*                                                                          */
/* HISTORY                                                                  */
/*                                                                          */
/*        NAME            DATE      REMARKS                                 */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
sshort NU_Xmit_Packet (uchar *pack_addr, uint16 num_msg_bytes)
{

   // according to IEEE802.3, packet length not including checksum
	   // should be at least 60 bytes.
	   // and the hardware will add CRC automatically.
	   // we say that CRC will be appended by transmitter, what's the
	   // meaning of it? length is actual size of the packet or
	   // the size should be actual size plus 4(CRC length?).
	   // refer to data sheet, size is only actual size.
	   if ( num_msg_bytes % 2 )
		   num_msg_bytes++;
	   if ( num_msg_bytes < TRANSMIT_BUF_MIN_SIZE )
		   num_msg_bytes = TRANSMIT_BUF_MIN_SIZE;		   // add PAD.
	   else if ( num_msg_bytes > TRANSMIT_BUF_SIZE ) 
		   return( -1 );								   // MTU exceeded.
			 
	   if ( NET_NO_ERROR != TransmitAPacket( (UINT16 *)pack_addr, num_msg_bytes / 2 ) )
		   return( -1 );
	   
	   return( NU_SUCCESS );
}



/*
Name:			OnTransmit
Description:	The interrupt routine core when a packet is transmit.
Parameters: 	None.
Return: 		None.

Test and revisioin:   Ason. 2001.5
*/
void OnTransmit(void)
{
	
	UCHAR tempc,regtemp;

	MacState.Tmt.TransmitTimes++;
	// read the state in.
	// SETTOPAGE0
	regtemp = inportb(TSRADD);
	
	if ( regtemp & 0x80 )
		MacState.Tmt.TransmitOWCErr++;
	if ( regtemp & 0x08 )
		MacState.Tmt.TransmitABTErr++;
	if ( regtemp & 0x02 )
		MacState.Tmt.TransmitColTimes++;
	if ( regtemp & 0x01 )
		MacState.Tmt.TransmitPTXTimes++;
	
	TransmitHappen = 1;
	PacketDelivered = 1;
}

/*
Name:			OnReceiveWithError
Description:	The interrupt routine core when a packet is received,
				but error is found.
Parameters: 	None.
Return: 		None.

Test and revisioin:   Ason. 2001.5
*/
void OnReceiveWithError(void)
{

	UCHAR tempc,regtemp;

	MacState.Rcv.PacketReceivedWithError++;

	// read the state in.
	// SETTOPAGE0
	regtemp = inportb(RSRADD);

	if ( regtemp & 0x02 )
		MacState.Rcv.PacketReceviedCRCErr++;
	if ( regtemp & 0x04 )
		MacState.Rcv.PacketReceviedFAEErr++;
	if ( regtemp & 0x08 )
		MacState.Rcv.PacketReceivedFIFOErr++;
	if ( regtemp & 0x10 )
		MacState.Rcv.PacketReceivedMissErr++;
	if ( regtemp & 0x40 )
		MacState.Rcv.PacketReceivedDisabled++;

   
}

/*
Name:			OnTransmitWithError
Description:	The interrupt routine core when a packet is transmitted,
				but an error is found.
Parameters: 	None.
Return: 		None.

Test and revisioin:   Ason. 2001.5
*/
void OnTransmitWithError(void)
{
	UCHAR tempc,regtemp;
	MacState.Tmt.TransmitTimesWithError++;

	// read the state in.
	// SETTOPAGE0
	regtemp = inportb(TSRADD);
	
	if ( regtemp & 0x80 )
		MacState.Tmt.TransmitOWCErr++;
	if ( regtemp & 0x08 )
		MacState.Tmt.TransmitABTErr++;
	if ( regtemp & 0x02 )
		MacState.Tmt.TransmitColTimes++;

	PacketDelivered = 1;
}

/*
Name:			RecoverFromBufShortage
Descriptioin:	This routine will be used to recover from
				the buffer shortage error. please refer to 796 data sheet.
Parameters: 	None.
Return: 		None.
Test and revision:
				Ason. 2001.8
*/
void RecoverFromBufShortage()
{
	uint16 txp, resend;
	UCHAR tempc;

	//	following lines are according to 88796 data sheet which 
	//	says very detailed about what to do when buffer overflows. 
	//	I change a little with throwing away all the packets waiting
	//	on the buffer link and make buffer empty.
	
	//	step 1, save TXP in 
	tempc = inportb(CRADD);
	if ( tempc & 0x04 )
		txp = 1;
	else 
		txp = 0;

	// step 2, stop 796
	outportb(CRADD,0x21);

	// step 3. wait for at least 1.5 ms.
	wait(2);
	
	// step 4, clear RBCR0 and RBCR1.
	SETTOPAGE0
	outportb(RBCR0ADD,0x00);
	outportb(RBCR1ADD,0x00);  

	// step 5
	if ( 1 == txp )
	{
		tempc = inportb(ISRADD);
		if ( ( tempc & 0x02 ) || ( tempc & 0x08 ) )
			resend = 0;
		else
			resend = 1;
	}
	else
	{
		resend = 0;
	}

	// step 6 loop, i know, this will shut the data link from out side.
	tempc = TcrSaver & 0xf9;
	tempc = TcrSaver | 0x02;
	outportb( TCRADD, tempc );

	// step 8. remove all the packet from the receive buffer.
	// as the packet has already been lost, just throw 
	// all the packets in the buffer away.
	// the method is set the two dynamic read and write
	// registers.
	outportb(BNRYADD,0x46);
	SETTOPAGE1
	outportb(CPRADD,0x47);
	SETTOPAGE0
	ReadPage = 0x47;  

	// step 9.
	outportb(ISRADD,0x10);

	// step 10.
	outportb(TCRADD, TcrSaver);

	// step 7. start. data sheet got some errors here,
	//				  if i start it really in step 7, data could 
	//				  still be flowed in of step 8,9,10, that could
	//				  make trouble.
	//				  step 6 will do this, but why do i find problems?
	outportb(CRADD,0x22);
	
	// step 11.
	if ( 1 == resend )
	{
	   outportb(CRADD,0x26);
	}
	
	// step 12. this is for my application environment.
	// when buffer shortage happens, there should be
	// also an receive interrupt.
	ReceiveIntHappen = 0;
	BufShortHappen = 0;

}

/*
Name:			OnShortBufferInReceive
Description:	The interrupt routine core when there is no buffer
				to save packet coming in.
Parameters: 	None.
Return: 		None.

Test and revisioin:   Ason. 2001.5
*/
void OnShortBufferInReceive(void)
{
	
	MacState.ShortBufferTimes++;
	BufShortHappen = 1;

}


/*
Name:			OnCounterOverflow
Description:	The interrupt routine core when the error counter
				is owverflow.
Parameters: 	None.
Return: 		None.

Test and revisioin:   Ason. 2001.5
*/
void OnCounterOverflow(void)
{
	// nothing to do.
	MacState.CouterOverflowTimes++;
}


/*
Name:			OnReset
Description:	The interrupt routine core when the MAC controller
				is reset.
Parameters: 	None.
Return: 		None.

Test and revisioin:   Ason. 2001.5
*/
void OnReset(void)
{
	// nothing to do.
	MacState.ResetTimes++;
}


/*
Name:			OnRemoteDMAComplete
Description:	The interrupt routine core when remote DMA finish the
				data transfer.
Parameters: 	None.
Return: 		None.

Test and revisioin:   Ason. 2001.5
*/
void OnRemoteDMAComplete(void)
{
	MacState.RemoteDMACompleteTimes++;
}


/*
Name:			MacInt
Description:	The MAC controller interrupt routine.
Parameters: 	None.
Return: 		None.

Test and revisioin:   Ason. 2001.5
*/
void MacInt(void)
{

	UCHAR tempc;
	UCHAR cr_saver;

	// first of all, read the CR, Command Register
	cr_saver = inportb( CRADD );
	if ( cr_saver & 0x40 )
	{
		// say, this is page 1
		// set to page 0, and there should be no problem
		// to generate retransmiting, as when we set to 
		// page0, there are destined to be no transmit.
		SETTOPAGE0
	}
	
	tempc = inportb(ISRADD);

	if ( tempc & 0x01 )  // this is a receive interrupt without any error.
	{
		OnReceive();
		outportb(ISRADD,0x01);
	}

	if ( tempc & 0x02 )
	{
		OnTransmit();
		outportb(ISRADD,0x02);
	}

	if ( tempc & 0x04 )
	{
		OnReceiveWithError();
		outportb(ISRADD,0x04);
	}

	if ( tempc & 0x08 )
	{
		OnTransmitWithError();
		outportb(ISRADD,0x08);
	}

	if ( tempc & 0x10 )
	{
		OnShortBufferInReceive();
		outportb(ISRADD,0x10);
	}

	if ( tempc & 0x20 )
	{
		OnCounterOverflow();
		outportb(ISRADD,0x20);
	}

	if ( tempc & 0x40 )
	{
		OnRemoteDMAComplete();
		// As we will clear this bit in polling mode,
		// we don't deal with it here.
	}

	if ( tempc & 0x80 )
	{
		OnReset();
	}

	NU_Activate_HISR( &NetControllerHisr );

	// and, return CR.
	if ( cr_saver & 0x40 )
	  // only recover when interrupt context is page1. 
	  outportb( CRADD, cr_saver );
  
}



/*
Name:		   RemoteRead
Description:   read data into a buffer use remote DMA.
Parameters:    cur_page: current page to start, may start at the middle
						 possition of a page.
			   len: 	 lenth of the DMA, words.
			   buf: 	 where to save data.
Return: 	   NET_NO_ERROR or error code.
Test and Revision:	 Ason, 2001.5
*/
INT16 RemoteRead(UINT16 cur_page, UINT16 len, UINT16 *buf)
{

	UCHAR tempc;
	UCHAR regtemp;
	UINT16 i;
	UINT16 tempss;
	UINT32 pre_int_level;

	
	// pre_int_level = NU_Control_Interrupts( MACINTLEVEL << 8 );
	// DISABLENETINTERRUPT
	

	SETTOPAGE0
	regtemp = (cur_page & 0xff00) >> 8;
	outportb(RSAR1ADD, regtemp);

	regtemp = cur_page & 0xff;
	outportb(RSAR0ADD,regtemp);

	regtemp = (( (len<<1) & 0xff00) >> 8) & 0xff;
	outportb(RBCR1ADD,regtemp);

	regtemp = (len<<1) & 0xff;
	outportb(RBCR0ADD,regtemp);

	// start remote DMA to read.
	outportb( CRADD,0x0a );  
	
	for (i = 0; i <len; i++ )
		*( buf + i ) = inport( DATAPORTADD );
	
	// wait for the read DMA to finish.
	i = 0;

	
	while(1)
	{
	   tempc = inportb(ISRADD);
	   if ( tempc & 0x40 )
	   {
		   MacState.RemoteDMACompleteTimes++;
		   break;
	   }
	   wait(1);
	   if ( i++ > NET_TMO_DMA )
		   break;
	}
	if ( i > NET_TMO_DMA )

⌨️ 快捷键说明

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