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

📄 driver.c

📁 mcf5307实验源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			return_value = NET_ERROR_DMAERR;
	}

	// wait for DMA to complete.
	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 )
		return( NET_ERROR_DMATMO );

	// clear the interrupt.
	outportb(ISRADD,0xff);

	ABORTDMA

	return( return_value );
}


/*
Name:			InitMacCntlr
Description:	Initialize MAC controller of 88796
Parameters: 	A string witch holds MAC address.
Return: 		mode - 0, loop; 1, normal.
				Only the work mode is set, the intrrupt routines
				are not set anyway.
Test and revisioin:   Ason. 2001.5
*/
void InitMacCntlr(UCHAR *mac_addr, INT16 mode)
{

	UCHAR tempc;

	// Step 1, turn to page 0 and set all those
	// important things in page 0,
	SETTOPAGE0

	// step 1.1
	// 0x21, stop the controller and abort remote DMA.
	outportb(CRADD,0x21);
	wait(3);
	
	// step 1.2    clear all interrupt and disable all interrupt.
	outportb(ISRADD,0xff);
	// the reset bit will not generate interrupt actually in 796
	outportb(IMRADD,0x00);

	// step 1.3
	// 0x03, DCR.  16-bit DMA transfering, byte order 68K
	//			   Dual 16-bit DMA mode, remote DMA is not always complete,
	outportb(DCRADD,0x03);
	
	// step 1.4
	// 0x00, TCR.	CRC appended by Transmitter.
	//				No loop back. 
	//				Half duplex, PAD enabled, Retransmite in 
	//				later collision, 88796 loop back.
	if ( 0 == mode )
	  outportb(TCRADD,0x22); 
	else
	  outportb(TCRADD,0x20); 
	TcrSaver = 0x20;		 
	
	// step 1.5
	// 0x24, RCR.	Packets with receive errors are rejected.
	//				reject runt packet.
	//				accept broadcast.
	//				not check multicast packet.   !!!
	//				Non promiscuous mode.
	//				normal mode.
	//				Low active interrupt.
	outportb(RCRADD,0x44);

	// step 1.6
	// DMA registers.
	// PSTARD set to 0x46. Attention, this is start address for receiving.
	outportb(PSTARTADD,0x46);
	
	// PSTOP  set to 0x80.
	outportb(PSTOPADD,0x80);
	
	// BNRY  set to 0x46.  Same as PSTARD.
	outportb(BNRYADD,0x46);
	
	// TSR, This is no use actually.
	outportb(TSRADD,0x40);
	// TBCR0
	outportb(TBCR0ADD,0x00);
	// TBCR1
	outportb(TBCR1ADD,0x00);
	// ISR, clear all ISR.
	outportb(ISRADD,0xff);
	// RSAR0ADD,
	outportb(RSAR0ADD,0x00);
	// RSAR1ADD,
	outportb(RSAR1ADD,0x40);
	// RBCR0ADD.
	outportb(RBCR0ADD,0x00);
	// RBCR1ADD.
	outportb(RBCR1ADD,0x00);

	// 1.7 Gap registers?
	// outportb(IFGS1ADD,0x00);
	// outportb(IFGS2ADD,0x00);
	// outportb(IFGADD,0x00);

	// 1.8	TPSRADD.
	outportb( TPSRADD,WritePage );

	// now, change to page 1.
	SETTOPAGE1
	// step 2.1
	// CURR
	outportb(CPRADD,0x47);
   
	// step 2.2
	// MAC Address 00001b182202 plus bednumber.
	outportb(PARA0ADD,*mac_addr);
	outportb(PARA1ADD,*(mac_addr+1));
	outportb(PARA2ADD,*(mac_addr+2));
	outportb(PARA3ADD,*(mac_addr+3));
	outportb(PARA4ADD,*(mac_addr+4));
	outportb(PARA5ADD,*(mac_addr+5));

	// step 2.3
	// multicast address, don't use multicast.
	outportb(MAR0ADD,0x00);
	outportb(MAR1ADD,0x00);
	outportb(MAR2ADD,0x00);
	outportb(MAR3ADD,0x00);
	outportb(MAR4ADD,0x00);
	outportb(MAR5ADD,0x00);
	outportb(MAR6ADD,0x00);
	outportb(MAR7ADD,0x00);

	ReadPage = 0x47;   // read page should be same with current page.
	WritePage = 0x40;  // actually, this will not change.

}


/*
Name:			SetIntRt
Description:	open interrupt and let NIC to work.
Parameters: 	None.
Return: 		None.
 
Test and revisioin:   Ason. 2001.5

*/
void SetIntRt(void)
{
	
	CHAR tempc;
	UINT16 temps;
  
	// enable the MAC controller in terrupt.
	// first of all, set to page 0.
	SETTOPAGE0

	// set all IMR.
	outportb(IMRADD,0x3f); // a reserve bit, and don't generate interrupt
						   // when remote DMA is finished.
	ImrSaver = 0x3f;
												 
	// clear all interrupt once more.
	SETTOPAGE0
	outportb(ISRADD,0xff);

	// clear CPU IMR.
	temps = *( (UINT16 *) ( IMR_ADDR ));
	temps &= 0xfffb; 
	*( (UINT16 *) ( IMR_ADDR )) = temps;

	// start the controller.
	STARTCNTLR
}

/*
Name:			OnReceive
Description:	The interrupt routine when a packet is received.
Parameters: 	None.
Return: 		None.

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

	MacState.Rcv.PacketReceived++;

	// read the state in.
	// don't set to page0 to make sure there are
	// no retransmit of a same packet.
	// SETTOPAGE0
	regtemp = inportb(RSRADD);

	if ( regtemp & 0x01 )
		MacState.Rcv.PacketReceivedIntact++;
	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 & 0x20 )
		MacState.Rcv.PacketReceivedBMpTimes++;
	if ( regtemp & 0x40 )
		MacState.Rcv.PacketReceivedDisabled++;
	
	ReceiveIntHappen = 1;

}




/****************************************************************************/
/* FUNCTION                                                                 */
/*                                                                          */
/*  NU_Get_Address                                                          */
/*                                                                          */
/* DESCRIPTION                                                              */
/*                                                                          */
/*  This function will handle reading the Ethernet address of the board from*/
/*  its internal memory. The base address of the board will be passed in    */
/*  for calculation offset to where the Ethernet address registers are.     */
/*  The Ethernet address will be checksumed when read in and tested to make */
/*  sure that the board is actually there. If the checksumming and masking  */
/*  shows that the board is missing, I/O address is wrong, etc and error    */
/*  will be returned.                                                       */
/*                                                                          */
/*                                                                          */
/* CALLED BY                                                                */
/*                                                                          */
/*    initbuffer, net.c file.                                               */
/*                                                                          */
/* CALLS                                                                    */
/*                                                                          */
/*                                                                          */
/* INPUTS                                                                   */
/*                                                                          */
/* uchar * : pointer to the location to store the read Ethernet address.    */
/* ulint   : Shared memory buffer for TCP/IP packets, not used.             */
/* ulint   : I/O base address of the board.                                 */
/*                                                                          */
/* OUTPUTS                                                                  */
/*                                                                          */
/*    sshort  : Returns a value of NU_FALSE if ok, else NU_TRUE on error.   */
/*                                                                          */
/* HISTORY                                                                  */
/*                                                                          */
/*    NAME                DATE        REMARKS                               */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
sshort NU_Get_Address (uchar *ether_addr, ulint not_used, ulint io_base)
{
    /* This routine is responsible for extracting the hardware address
     * from the hardware.  The hardware address should be copied into
     * the location pointed to by ether_addr.  If the hardware address is
     * successfully extracted a value of NU_SUCCESS (0) should be returned.
     * Else an error code should be returned (anything other than 0).
     */

	*ether_addr = 0x52;
	*(ether_addr + 1) = 0x54;
	*(ether_addr + 2) = 0x4c;
	*(ether_addr + 3) = 0xbd;
	*(ether_addr + 4) = 0xa1;
	*(ether_addr + 5) = 0x1a;
	
    return (NU_SUCCESS);

}        /* end NU_Get_Address routine */

/****************************************************************************/
/* FUNCTION                                                                 */
/*                                                                          */
/*  NU_Set_Address                                                          */
/*                                                                          */
/* DESCRIPTION                                                              */
/*                                                                          */
/*  This function will handle loading the Ethernet address of the board into*/
/*  its internal memory. The base address of the board will be passed in    */
/*  for calculation offset to where the Ethernet address registers are.     */
/*                                                                          */
/* CALLED BY                                                                */
/*                                                                          */
/*    No functions call this function.                                      */
/*                                                                          */
/* CALLS                                                                    */
/*                                                                          */
/*                                                                          */
/* INPUTS                                                                   */
/*                                                                          */
/* uchar * : pointer to the location to the read Ethernet address from.     */
/* ulint   : Shared memory buffer for TCP/IP packets, not used.             */
/* ulint   : I/O base address of the board.                                 */
/*                                                                          */
/* OUTPUTS                                                                  */
/*                                                                          */
/*    No outputs from this function.                                        */
/*                                                                          */
/* HISTORY                                                                  */
/*                                                                          */
/*    NAME                DATE        REMARKS                               */
/*                                                                          */
/*                                                                          */
/****************************************************************************/
void NU_Set_Address (uchar *ether_addr, ulint not_used, ulint io_base)
{
   /*  This function will handle loading the Ethernet address of the board
    *  into its internal memory. The base address of the board will be passed
    *  in for calculation offset to where the Ethernet address registers are.
    */

}        /* end NU_Set_Address routine */



/****************************************************************************/
/* FUNCTION                                                                 */
/*                                                                          */
/*    NU_Recv_Packet                                                        */
/*                                                                          */
/* DESCRIPTION                                                              */
/*                                                                          */
/*    This function will handle the incomming data packets to the Ehternet  */
/*    board. The routine can be called though the use of and interrupt or   */
/*    polling. It will handle the parsing and storing of the current packet */
/*    from the wire.                                                        */
/*                                                                          */
/* CALLED BY                                                                */
/*                                                                          */
/*    demux in file net.c                                                   */
/*    NU_Ether_Inter_RTX                                                    */
/*    NU_Ether_Inter_PLUS                                                   */
/*                                                                          */
/* CALLS                                                                    */
/*                                                                          */
/*    memcpy (uchar *, uchar *, int);                                       */
/*    dll_update_lists                                                      */
/*                                                                          */
/* INPUTS                                                                   */
/*                                                                          */
/*    No inputs to this function.                                           */
/*                                                                          */
/* OUTPUTS                                                                  */
/*                                                                          */
/*    sshort : Returns status as to buffer processing NU_TRUE if ok         */
/*             NU_FALSE if and error.                                       */
/*                                                                          */
/* HISTORY                                                                  */
/*                                                                          */
/*        NAME            DATE      REMARKS                                 */
/*                                                                          */
/****************************************************************************/
sshort NU_Recv_Packet (void)
{
   uchar *recv_data_ptr;      /* pointer to the received data in shared memory */
   ushort total_bytes;        /* total byte for this packet */
   struct pqueue HUGE *buf_ptr;


    /* This function is called from the receive HISR.  It is responsible
     * for moving received packets from shared memory into the packet buffers.
     */

     /* An example of how a buffer is allocated and used. */

         /* Allocate a partition into which the received packet will be copied. */
         buf_ptr = dll_update_lists(&buffer_freelist, &buffer_list);

         /* If the allocation failed then cleanup and return.
          */
         if (buf_ptr == NU_NULL)
         {
             /*  If the partition allocation failed for any reason other than
              *  there were no partitions currently available, generate an
              *  error message.
              */
             if (buf_ptr == NU_NULL)
             {
                  NU_Tcp_Log_Error (TCP_PARTITION_ERROR, TCP_RECOVERABLE,
                        __FILE__, __LINE__);
             }

             /* return that there was an error with a packet reception */
             return NU_FALSE;
         }   /* end check for room in our buffer */


         /*
          * Transfer the data from the packet to our memory.
          */

         /* transfer the frame(s) from the shared memory to ours */
         if (total_bytes != 0)
         {
                 /* store the contiguous message */
                 memmove(buf_ptr->packet, recv_data_ptr, total_bytes);

         }   /* end transfer the data from the shared mem, to our buffer */

   return NU_TRUE;
}  /* end NU_Recv_Packet routine */

/*
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
*/
int16 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_level;
	UINT16 tempss;

	
	//	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)
	//	Attention, this change of "preempt" feature is 
	//	used to protect seed of "protect"!!!
	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 );	
	DISABLENETINTERRUPT
	

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

	outportb( TPSRADD,WritePage );

⌨️ 快捷键说明

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