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

📄 netdrv.cpp

📁 coldfire5206芯片平台的自捡程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	// 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 ( TRUE == 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
	cr_saver = inportb( CRADD );

    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();
    }

	// and, return CR.
	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;
	UINT32 pre_int_level;

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

	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 )
	{
  //      NU_Control_Interrupts( pre_int_level );
		return( NET_ERROR_DMATMO );
	}

	outportb( ISRADD, 0x40 );
    
//	NU_Control_Interrupts( pre_int_level );
	return( NET_NO_ERROR );

}


/*
Name:          RemoteWrite
Description:   write data into a buffer using 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 copy the data.
Return:        NET_NO_ERROR or Error code.
Test and Revision:   Ason, 2001.5
*/
BOOL RemoteWrite(UINT16 cur_page, UINT16 len, UINT16 *buf)
{
    CHAR tempc;
    UCHAR regtemp;
    UINT16 i;

    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 write.
    outportb( CRADD,0x12 );   

	// buf maybe exceed the scope for adding pads, but
	// it just read, do no harm.
    for (i = 0; i <len; i++ )
		outport(DATAPORTADD, *(buf + i));
			
    // wait for the read DMA to finish.
	i = 0;
	while(1)
	{
      tempc = inportb(ISRADD);
	  if ( 0x40 & tempc )
	  {
	      MacState.RemoteDMACompleteTimes++;
		  break;
	  }
	  wait(1);
	  if ( i++ > NET_TMO_DMA )
		  break;
	}
	if ( i > NET_TMO_DMA )
		return( NET_ERROR_DMATMO );

    outportb(ISRADD,0x40);  // clear DMA interrupt.

	return( NET_NO_ERROR );

}

/*
Name:         TransmitAPacket
Description:  Transmit a packet promptly.
Parameters:   buf - buffer to hold the packet, point to word.
              length - length in word
Returns:      NET_NO_ERROR or Error code.
Test and revision:
              Ason.  2001.7
*/
INT16 TransmitAPacket( UINT16 *buf, UINT16 length )
{
    UCHAR tempc,regtemp;
	UINT16 temps;
	INT16 return_value,i;
	UINT32 pre_int_lev;

	
	//  I am pretty sure this will be called only in
	//  tasks, so, change to NO_PREEMPTION to solve
	//  conflict of the two protocols.( TCP/IP and VB)
	// NU_Change_Preemption( NU_NO_PREEMPT );
    
	//  I could not use IMR in 88796(don't know why?), and 
    //  I don't wanna disabling of this interrupt influence
    //  low level interrupts, so, I just use CPU IMR. IMR could
	//  only mask low level interrupt, back to CR.
	// pre_int_lev = NU_Control_Interrupts( MACINTLEVEL << 8 );  
	

	return_value = RemoteWrite( ((UINT16)WritePage) << 8 , length, buf );
	if ( NET_NO_ERROR != return_value )
	{
//        NU_Change_Preemption( NU_PREEMPT );
	    //NU_Control_Interrupts( pre_int_lev );  
		return( return_value );
	}

    outportb( TPSRADD,WritePage );

	// length is destined to be even.
	outportb(TBCR0ADD,(length<<1) % 256);
    outportb(TBCR1ADD,(length<<1) / 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( TRUE )
	{
		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 );  
	//	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( TRUE )
	{
		// 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 ) )
			break;
	 	wait(1);
        if ( i++ > NET_TMO_TMIT )
			break;
	}
	
	//NU_Change_Preemption( NU_PREEMPT );
	if ( i > NET_TMO_TMIT )
		return( NET_ERROR_TRANSBLOCK );
	else 
	    return( NET_NO_ERROR );

}


/*
Name:         ConfigMacMii
Description:  set neccessary things in MII register set, 
              as 10M/100M, duplex and such staff.
Parameters:   mode, 0 - 10M, 1-100M, 2- autonegotiation.
Return:       TRUE, success, FALSE, fail.
Test and revision:
              Ason, 2001.7.
*/
INT16 ConfigMacMii(INT16 mode)
{

    INT16 return_value;
	UINT32 i;
	UINT16 tempus;
	UCHAR tempc;

	SETTOPAGE0
	outportb(CRADD,0x21);
	wait(3);

    // reset MII register set.
	tempus = 0x8000;
	WriteMiiRegister(0x10,0x00,tempus); // 0x10 is the PHY ID of our internal PHY,
	                                    // you may refer to 88796 data sheet. 
	i = 0;
	while( TRUE )
	{
       return_value = ReadMiiRegister(0x10,0x00,&tempus);
	   if (  NET_NO_ERROR != return_value )
		   return( NET_ERROR_PHYREAD );
	   if ( ! ( tempus & 0x8000 ) )
		   break;
       wait(1);
	   if ( i++ > NET_TMO_MIIRST )
		   return( NET_ERROR_MIIRST );
	}
	
	tempus &= 0xcfff;      // clear 10/100/auto-negotiation bit.
	if ( 2 == mode)
	  tempus |= 0x1000;    // set auto negotiation.  
	else if ( 1 == mode )
	  tempus |= 0x2000;    // set to 100M.
	
	tempus &= 0xfeff;       // set to half duplex.
	WriteMiiRegister(0x10,0x00,tempus);

	// say i am not capable of 100Base-TX and 100Base-T.
	// Why say I am not capable of 100M?s
	// WriteMiiRegister(0x10,0x04,0x0061);
	
	// say i will see interrupt of link state/jabber/remote fault/false carrier.

⌨️ 快捷键说明

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