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

📄 cs8900.c

📁 cs8900网卡在嵌入式系统中的驱动,网上很少有此网卡驱动的源代码,并且cs8900的datasheet写的非常乱,这个网卡驱动是我用了快2个星期弄出来的,分享给大家,希望大家少走弯路.
💻 C
📖 第 1 页 / 共 2 页
字号:
{
   	 int j,i;
	 unsigned short status;

	/* Reset chip */
	 WritePPRegister(PP_SelfCtl, (unsigned short)PP_SelfCtl_Reset);  

	 /* Wait about 125 msec for chip resetting in progress */ 
	
	//	 省略	
	Delay(10);

	 /* check the PP_SelfStat_InitD bit if the chip successflly reset */
	 for (i=0;i<10;i++)
	 {
		 for (j=0; j<3000; j++) 
		 {
		   status=(ReadPPRegister(PP_SelfStat) & PP_SelfStat_InitD);
		   
		   if ( status != 0 ) 
		   {
	         	 return 0  /* successful */;
		   }	   
		 }
	} 	
	 return -1; /* fail */
}

//获取要传送数据的总长度,host传到cs的数据长度
U16 get_frame_len(unsigned char *dataBuf)
{
	U16 *ptr = (U16*)dataBuf;
	ptr += 6;
	
	return *ptr;
}

/**************************************************************************/
/* cs8900_poll_send():  Transmit a frame in Poll mode.                    */
/**************************************************************************/
int cs8900_poll_send(unsigned char *dataBuf)
{
    int len;
    unsigned short *sdata;
    unsigned short stat;
    unsigned long i;
    int total_len = get_frame_len(dataBuf) + 14;	
  
 //   Uart_Printf("ss%d\n", total_len);

   /****** Step 0: First thing to do is to disable all interrupts at processor level.*/	
   /****** Step 1:  Write the TX command */
     if ( gPrevTxBidFail ) 
	{
		/* Previous BidForTX has reserved the Tx FIFO on CS8900, must clear off it.*/
		/* Setting PP_TxCmd_Force bit will cause CS8900 to release the previous reserved Tx buffer.*/
		CS8900_TxCMD = (unsigned short) PP_TxCmd_TxStart_Full | PP_TxCmd_Force;
		gPrevTxBidFail=0;
	} 
	else 
	{
		CS8900_TxCMD =  (unsigned short) PP_TxCmd_TxStart_Full;
	}

 printf("\n----------Start Translate--------\n");
	/****** Step 2: Bid for Tx ******/
	/* Write the frame length  (number of bytes to TX) */
	/* Note: After the frame length has been written, CS8900 reserves Tx buffer for this bid no
	         matter PP_BusStat_TxRDY is set or not.*/
	CS8900_TxLEN  = total_len;
 
	/* Read BusST to verify it is set as Rdy4Tx. */
	stat = ReadPPRegister(PP_BusStat);


	/****** Step 3: check if TxBidErr happens ******/
	if ( stat & PP_BusStat_TxBid ) 
	{    /*TxBidErr happens only if Tx_length is too small or too large. */
         printf(" Tx Bid Error! TxLEN=%d \n", total_len);
          printf("----------End Translate-------------\n");

		 /****** Step 3.1: enable interrupts at processor level if it is disabled in step 0.******/
         /*enable( );   */
	  	 return -1;
	}
    

	/****** Step 4: check if chip is ready for Tx now ******/
      /* If Bid4Tx not ready, skip the frame */
     // while ( (stat & PP_BusStat_TxRDY) == 0);
	if ( (stat & PP_BusStat_TxRDY) == 0)
	{
	
	 /* If not ready for Tx now, abort this frame.*/
         /* Note: Another alternative is to poll PP_BusStat_TxRDY until it is set, if you don't want to
		          abort Tx frames.*/ 
         gPrevTxBidFail=1;/* set to 1, and next time if cs8900_poll_send() is called, it can 
						  set PP_TxCmd_Force to clear off the reserved Tx buffer in CS8900 chip.*/

         printf("Tx Bid Not Ready4Tx! \n");
          printf("------End Translate-------\n");
		 
		 /****** Step 4.1: enable interrupts at processor level if it is disabled in step 0.******/
         return -1;
    }       
 
printf("Start to Translate\n");

/****** Step 5: copy Tx data into CS8900's buffer*/
    /* This actually starts the Txmit*/
    sdata = (unsigned short *)dataBuf;
    len = total_len;
    if (len > 0) 
    {
        /* Output contiguous words, two bytes at a time. */
        while (len > 1) 
	{
	       CS8900_RTDATA = *sdata;
		sdata++;
	       len -= 2;
	       printf(".");
        }
        
        

        /* If Odd bytes, copy the last one byte to chip.*/
        if (len == 1) 
	{
           CS8900_RTDATA = (*sdata) & 0x00ff;
        }
    }
printf("\nEnding  Translate\n");

    /****** Step 5.1: enable interrupts at processor level if it is disabled in step 0.******/
    /*enable( );   */


	/****** Step 6: Poll the TxEvent Reg for the TX completed status */
	/* This step is optional. If you don't wait until Tx compelete, the next cs8900_poll_send() 
	  Bid For Tx may encounter Not Ready For Tx because CS8900 is still Tx'ing.*/
	for ( i=0; i<30000; i++) 
	{
	        stat = ReadPPRegister(PP_TER);
	        
	        if ( stat != 0x0008 ) 
		{
	            break;
	        }
	}
	
	/* Tx compelete without error, return total_length Tx'ed */
	if ( (stat & PP_TER_TxOK) || (stat == 0x0008) ) 
	{
		printf("Translate successful \n");
		 printf("----------End Translate-------\n");
            return total_len; /* return successful*/
	} 
	/* Tx with Errors */
	printf("Tx Error! TxEvent=%x \n", stat);
	printf("----------End Translat--------\n");
	return -1; /* return failed*/
}


/**************************************************************************************/
/* cs8900_poll_recv(): can be used to receive a frame in  Poll mode.                  */
/**************************************************************************************/
int cs8900_poll_recv( unsigned char *dataBuf)
{
    unsigned short stat, totalLen, val;
    int leftLen;
    unsigned short *data;
    unsigned char *cp;

    /****** Step 1: check RxEvent Register ******/
	stat = ReadPPRegister(PP_RER);

    /****** Step 2: Determine if there is Rx event. ******/
	/* If nothing happened, then return. 0x0004 is the register ID.
	   If some bits in Bit 6 - Bit 15 are set, some Rx event happened. */
	if ( stat == 0x0004 ) 
	{
		return 0;
	}


    /****** Step 3: Determine if there is Rx Error. ******/
	/* If RxOk bit is not set, Rx Error occurred  */
	if ( !(stat & PP_RER_RxOK) ) 
	{
		if (  stat & PP_RER_CRC) 
		{
 		    printf("cs8900_poll_recv(): received frame with CRC error.\n"); 
		} 
		else if ( stat & PP_RER_RUNT) 
		{
			printf("cs8900_poll_recv(): received frame with RUNT error.\n"); 
		}
		else  if (stat & PP_RER_EXTRA ) 
		{
			printf("cs8900_poll_recv(): received frame with EXTRA error.\n"); 
		}
		else 
			printf("cs8900_poll_recv(): Unknown Error: stat=%x \n", stat);

         /****** Step 4: skip this received error frame. ******/
         /* Note: Must skip this received error frame. Otherwise, CS8900 hangs here. */
		/* Read the length of Rx frame */
      		
	      	totalLen= ReadPPRegister(PP_Rx_LENGTH);
		
		/* Write Skip1 to RxCfg Register and also keep the current configuration.*/
		val = ReadPPRegister(PP_RxCFG);
		val |= PP_RxCFG_Skip1; 
	    	WritePPRegister(PP_RxCFG, val);
		return -1; /* return failed */
    	}
    	
printf("\n--------Start Receive Data--------------\n");
 	 /****** Step 5: Read the length of Rx frame ******/
     totalLen = ReadPPRegister(PP_Rx_LENGTH);

	 /* uncomment printf for debugger purpose.*/
	printf("RxEvent - stat: %x, len: %d\n", stat, totalLen);

     
 	 /****** Step 6: Read the Rx data from Chip and store it to user buffer ******/
    data = (unsigned short *)dataBuf;
    leftLen = totalLen;

	/* read 2 bytes at a time */
    while (leftLen >= 2) 
    {
	   *data++ = CS8900_RTDATA;
          leftLen -= 2;
    }

	/* if odd bytes, read the last byte from chip*/
    if (leftLen == 1) 
    {
	/* Read the last byte from chip*/
		val = CS8900_RTDATA;
        /* point to the last one byte of the user buffer*/
        	cp = (unsigned char *)data;

	   /* truncate the word (2-bytes) read from chip to one byte */
      		 *cp = (unsigned char)(val & 0xff);
    }
	return (int)totalLen;
}




/**************************************************************************************/
/* 发送数据,长度为dataLen                 */
/*参数pData 为host准备发送的缓冲区,dataLen为本缓冲区欲发送数据的长度,在发送函数里,总的数据长度应length+物理地址长度+目的地址长度+数据长度位(2)*/
/**************************************************************************************/
//使用gTxDataBuf作为发送缓冲区
S16  s3c2410_eth_send(const char*pData,const U16 dataLen)
{
	unsigned char *pRoller;
	U16 *temp;
	S16 stat;
	int i; 
	
	pRoller=(unsigned char * )gTxDataBuf;
	
	//写目的地址
	memcpy(pRoller, EtherDesAddr, 6);    
	pRoller +=6;

    	//写源地址
	memcpy(pRoller, EtherAddr, 6);
	pRoller +=6;
    
	temp = (U16 *)pRoller;    
	* temp = dataLen;	
	
	pRoller+=2;  
	
	memcpy(pRoller, pData,dataLen);
/*	for (i = 0; i < 6; i ++) 
		Uart_Printf("%x", gTxDataBuf[i]);
	Uart_Printf("\n");
	
	for (; i < 12; i ++)
		Uart_Printf("%x", gTxDataBuf[i]);
	Uart_Printf("\n");
	
	Uart_Printf("%d\n", (int *)gTxDataBuf[i ++]);
	
	for (; i < dataLen + 15; i ++)
		Uart_Printf("%c", gTxDataBuf[i]);
	Uart_Printf("\n"); */
	
	stat =  cs8900_poll_send((unsigned char * )gTxDataBuf);
	return stat;
}

/*
//发送数据
int data_send_cs()
{
	creat_send_data();
}*/
/*
//创建用来发送的数据,把要出送的数据组装成以太网桢
void creat_send_data(void)
{
	unsigned char *pRoller;
	pRoller = (unsigned char * )gTxDataBuf;
	
	//写目的地址
	memcpy(pRoller, EtherDesAddr, 6);    
	pRoller +=6;
	
	//写源地址
	memcpy(pRoller, EtherAddr, 6);
	pRoller +=6;	
		
}
*/


//接收包,阻塞函数,一直等到有数据过来,要么错误要么正确
S16  s3c2410_eth_receive(unsigned char* dataBuf)
{
	unsigned short stat = 0;	
	
	printf("\nReceive Pool \n");
	
	while (stat == 0)
	{
		stat = cs8900_poll_recv(dataBuf);
		printf(".");
	}
	
	printf("\n");
	if (stat >0)
	{	
		printf("Receive data OK,Length is %d\n",stat);
	}
	else
	{
		printf("Receive data Error\n");
	}	
	printf("--------End Receive Data--------------\n");
        
	return (int)stat;
	
}

//判断电缆是否插好
int s3c2410_line_plug()
{
	U16 stat;
	stat = ReadPPRegister(PP_LineStat);
	
	//电缆没有插好
	if (!(stat & PP_LineStat_LinkOK)) {
		Uart_Printf("电缆没有插好!\n");
		return -1;
	}
	else
		return 1;
}

⌨️ 快捷键说明

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