DM9000 8bit 模式时, 初始化, 接收及发送函数

版权声明:随便转, 随便转.... https://blog.csdn.net/KISSMonX/article/details/38302931
#include "dm9000a1.h"
#include "dm9000a.h"
#include "gpio.h"
#include "timer.h"
#include "net.h"

// 这个当然只是勉强好用的版本, 完美版本得自己留着, 公司产权.....2333333333333
// 本地全局变量
static uu8   ether_addrress[6];	////物理地址
static uu32  multimac_mcastFilter[2];


// 软件延时, 初始化硬件使用
static void  delay_ms(unsigned int dels)
{
	unsigned  int x = 0;
	
	while (--dels) {
		for (x = 0; x < 2290; x++)
			;
	}
}

//==============================================================================================
////写入dm9000a基本寄存器
static void dm9000a_iow(uu8  reg, uu8  datas)
{
	IOWR(DM9000A_CMD_ADDR_1, reg);
	IOWR(DM9000A_DAT_ADDR_1, datas);
}


//==============================================================================================
////读取dm9000a基本寄存器
static uu8 dm9000a_ior(uu8  reg)
{
	IOWR(DM9000A_CMD_ADDR_1, reg);
	return (IORD(DM9000A_DAT_ADDR_1) & 0xFF);
}


//==============================================================================================
////写入dm9000aPHY寄存器
static void dm9000aphy_iow(uu8  reg, uu16  datas)
{
	dm9000a_iow(DM9000A_PHYAR, 0x40 + reg);
	dm9000a_iow(DM9000A_PHYDLR, datas & 0xff);
	dm9000a_iow(DM9000A_PHYDHR, (datas >> 8) & 0xff);
	dm9000a_iow(DM9000A_PHYCR, 2 + 8);
	while(dm9000a_ior(DM9000A_PHYCR) & 1);	// 等待写入完毕
	dm9000a_iow(DM9000A_PHYCR, 0x08);	// 清除 PHY 写操作命令
}


//==============================================================================================
////读取dm9000aPHY寄存器
static uu32 dm9000aphy_ior(uu8  reg)
{
	uu32 datas = 0;

	dm9000a_iow(DM9000A_PHYAR, 0x40 + reg);
	dm9000a_iow(DM9000A_PHYCR, 4 + 8);
	while(dm9000a_ior(DM9000A_PHYCR) & 1); 	// 等待读操作完成
	datas = ((dm9000a_ior(DM9000A_PHYDHR) << 8) | dm9000a_ior(DM9000A_PHYDLR));
 	dm9000a_iow(DM9000A_PHYCR, 0x08); 	// PHY 读命令寄存器清零
	return datas;
}

//==============================================================================================
////读取DM9000A基本标识信息
static uu32 dm9000a_Info(void)
{
	uu32  id_val = 0;

	id_val  = dm9000a_ior(DM9000A_VIDL);
	id_val |= (uu32)dm9000a_ior(DM9000A_VIDH) << 8;
	id_val |= (uu32)dm9000a_ior(DM9000A_PIDL) << 16;
	id_val |= (uu32)dm9000a_ior(DM9000A_PIDH) << 24;
	
	return id_val;
}

//==============================================================================================
////读取DM9000APHY标识信息
static uu32 dm9000aphy_Info(void)
{
	uu32  id_val = 0;

	id_val  = dm9000aphy_ior(DM9000APHY_ID1R);
	id_val |= dm9000aphy_ior(DM9000APHY_ID2R) << 16;

	return id_val;
}


//==============================================================================================
////组播模式设置
static void dm9000a_addrfilterset(uu8 *hash_table)
{
	uu8 i;

	hash_table[7] |= 0x80;
	for (i = 0; i < 8; i++) {
		dm9000a_iow(DM9000A_MAR + i, hash_table[i]);
	}
}


//==============================================================================================
// 网卡初始化
static void dm9000a_init(void)
{
	uu8   i = 0;
	uu8   IO_Mode = 0;		// IO 口 模式 8/16bit
	uu32  dm9000a_ID = 0;		// 低 16 位: vendor ID  高 16 位: product ID
	uu32  dm9000aphy_ID = 0;
	u8    link;
	u8    speed;
	u8    duplex;
	
	gio_clr(DM9000A_RST_ADDR_1);
	delay_ms(5);
	gio_set(DM9000A_RST_ADDR_1);
	delay_ms(5);
	
	dm9000a_iow(DM9000A_GPR, 0); 		// 激活内部PHY
	delay_ms(20);				// 延时
	
	
	dm9000a_iow(DM9000A_NCR, 0x03);		// 软复位第一次,mac lookback on
	delay_ms(20);
	dm9000aphy_iow(DM9000APHY_BMCR, 0x8000);//PHY复位
	i = 0;  
	do { 
		delay_ms (1);
	} while ( (i++ < 200) && !( dm9000a_ior(DM9000A_NSR) & 0x40) );
	
	dm9000aphy_iow(DM9000APHY_ANAR, 0x01E1 | 0x0400);  /* operating PHY media mode with H/W Flow-control */
	dm9000aphy_iow(DM9000APHY_BMCR, 0x1200); //PHY复位
	
	i = 0;  
	do { 
		delay_ms (1);
	} while ( (i++ < 200) && !( dm9000a_ior(DM9000A_NSR) & 0x40) );
	delay_ms (5);
	
	/* set other registers depending on applications */ 
	dm9000a_iow(DM9000A_IMR, 0x80);		/* IMR enable only Pointer Auto Return for RX/TX FIFO SRAM */
	dm9000a_iow(DM9000A_BPTR, 0x3f);	/* BPTR REG.08(if necessary) High Water Overflow 3KB, 600us */ 
	dm9000a_iow(DM9000A_FCTR, 0x5A);	/* FCTR REG.09 (if necessary) High/ Low Threshold 5KB/ 10KB */	
	dm9000a_iow(DM9000A_RXTXFCR, 0x29);	/* FCR REG.0AH enable TXPEN, BKPM (for TX_half), FLCE (RX) */
	
	//dm9000a_addrset(ether_addrress);	////设置MAC地址
	for (i = 0; i < 6; i++) {
		dm9000a_iow(DM9000A_PAR + i, ether_addrress[i]);
	}
	dm9000a_addrfilterset((uu8 *)&multimac_mcastFilter[0]);	// 设置组播模式
	
	dm9000a_iow(DM9000A_NCR, 0);		/* enable chip functions and disable loopback back to normal*/ 
	
	 /* clear any pending interrupt */ 
	dm9000a_iow(DM9000A_NSR, 0x2c);		/* clear NSR 3bits status: TX1END, TX2END, WAKEST by RW/C1 */
	dm9000a_iow(DM9000A_ISR, 0x3F);		/* clear ISR status: PR,PT, ROS,ROO, UDRUN, LNKCHG by RW/C1 */
	
	/* enable Rx interrupts ~go */ 
	dm9000a_iow(DM9000A_IMR, 0x81);	 	/* IMR REG. FFH enable PAR+ PTI+PRI+ROI+ROOI+UDRUNI+LNKCHGI */
	
	/* enable RX Broadcast/ ALL MULTICAST to activate DM9000A ~go */ 
	dm9000a_iow(DM9000A_RXCR, 0x31);
	
	/* initialize the driver variables or the user passed arguments */ 
	IO_Mode = dm9000a_ior(DM9000A_ISR);	//最高位 1: 8bit  0: 16bit 
	dm9000a_ID = dm9000a_Info();		//
// 	printf("DM9000A-1 Vendor ID and Product ID: %x", dm9000a_vendor_ID);
	dm9000aphy_ID = dm9000aphy_Info();
// 	printf("DM9000A-1 PHY ID Identifier: %x", dm9000aphy_ID)
	link  = (dm9000a_ior(DM9000A_NSR) & 0x40) ? 1 : 0;	 // bit.6 = 1: link ok
	speed = (dm9000a_ior(DM9000A_NSR) & 0x80) ? 10 : 100; 	 // bit.7 = 0: 100Mbps
	duplex = (dm9000a_ior(DM9000A_NCR) & 0x8) ? 1 : 0; 	 // bit.3 = 1: Full Duplex mode
	delay_ms(1);
}


//==============================================================================================
// 描述: DM9000 底层发送函数
// 参数: head 发送数据的起始地址
//       buflen 发送数据长度
//       pbuf  
// 返回: 成功 0, 这里有点别扭
uu8 dm9000a_1_ptran(uu8 *head, uu16 buflen, uu8 *pbuf)
{
	uu32  i;
	uu16  tx_len;
	uu8 * data_ptr;
	
//	P3 = 0x00;	// 测试发送时间,大约 5ms/1500 字节
	
//	dm9000a_iow(DM9000A_ISR, 0x02); /* Clear Tx bit in ISR */
//	dm9000a_iow(DM9000A_IMR, 0x80); // 关闭网卡中断
	/* Move data to DM9000 TX RAM */
	IOWR(DM9000A_CMD_ADDR_1, DM9000A_MWCMD); /* Prepare for TX-data */
	
	data_ptr = (uu8 *)head;
	for (i = 0; i < sizeof(ETH_HEADER); i++) {
		IOWR(DM9000A_DAT_ADDR_1, *data_ptr++);
	}
	
	data_ptr = (uu8 *)pbuf;
	for (i = 0; i < buflen; i++) {
		IOWR(DM9000A_DAT_ADDR_1, *data_ptr++);
	}
	
	tx_len = buflen + 14;
	dm9000a_iow(DM9000A_TXPLL, (tx_len) & 0xff);
	dm9000a_iow(DM9000A_TXPLH, tx_len >> 8);
	dm9000a_iow(DM9000A_TXCR, 1 | DM9000A_TXCR_INIT_VAL); 
	while((dm9000a_ior(DM9000A_NSR) & 0x0c) == 0);
	dm9000a_iow(DM9000A_NSR, 0x2c);
//	dm9000a_iow(DM9000A_IMR, 0x81); // 重新开启网卡中断接收
	
//	P3 = 0xFF;	// 测试发送时间
	
	return 0;
}


//==============================================================================================
// DM9000 接收数据函数
// 返回数据长度
uu16 dm9000a_1_prcv(uu8 *eth_head, uu8 *pdata_buf)
{
	uu16  i = 0;
	uu8  temp_rx = 0;
	uu8   Rx_Byte;
	uu16   Rx_Status;
	uu16  Rx_Len = 0;
	uu8 * data_ptr;
	
	 /* Rx-ISR bit must be set. */
	if (!(dm9000a_ior(DM9000A_ISR) & 0x01)) {
		return 0;
	}

	dm9000a_iow(DM9000A_IMR, 0x80); // 关闭网卡中断
	/*****************************************************************************************
	* DM9000从网络中接到一个数据包后,会在数据包前面加上 4 个字节,分别为 “01H”、
	* “status”(同RSR寄存器的值)、“LENL”(数据包长度低 8 位)、“LENH”(数据包长度高 8 位)。
	* 所以首先要读取这 4 个字节来确定数据包的状态,第一个字节 “01H” 表示接下来的是有效数据包,
	* 若为“00H”则表示没有数据包,若为其它值则表示网卡没有正确初始化,需要从新初始化。
	* 如果接收到的数据包长度小于 60 字节,则 DM9000 会自动为不足的字节补上 0,使其达到 60 字节。
	* 同时,在接收到的数据包后 DM9000 还会自动添加 4 个 CRC 校验字节。可以不予处理。
	* 于是,接收到的数据包的最小长度也会是 64 字节。
	******************************************************************************************/
	/* Get most updated data, only look at bits 0:1, See application notes DM9000 */
	dm9000a_ior(DM9000A_MRCMDX); // 第一次读取一般都是 0x00
	Rx_Byte = IORD(DM9000A_DAT_ADDR_1) & 0x03;	// 第二次总能读到数据
	/* Status check: this byte must be 0 or 1 */
	if(Rx_Byte > DM9000A_PKT_RDY) {
		dm9000a_iow(DM9000A_RXCR, 0x00); /* Stop Device */
		dm9000a_iow(DM9000A_ISR, 0x80);  /* Stop INT request */
		return 0;
	}

	if (Rx_Byte != DM9000A_PKT_RDY) {
		dm9000a_iow(DM9000A_ISR, 0x01);  /* clear PR status latched in bit 0 这个要放在没有数据包时候, 不然多个数据包到来, 就会出现通一会就断开连接*/ 
		return 0; /* No packet received, ignore */
	}
	
	/* A packet ready now  & Get status/length */	
	IOWR(DM9000A_CMD_ADDR_1, DM9000A_MRCMD);	// 将 memory write cmd 写入 addr 上
	
	Rx_Byte	  = IORD(DM9000A_DAT_ADDR_1);
	Rx_Status = IORD(DM9000A_DAT_ADDR_1); 
	Rx_Len    = IORD(DM9000A_DAT_ADDR_1);
	Rx_Len    |= (uu16)(IORD(DM9000A_DAT_ADDR_1) << 8);
	

	data_ptr = (uu8 *)eth_head;
	for (i = 0; i < sizeof(ETH_HEADER); i++) {	
		*data_ptr++ = IORD(DM9000A_DAT_ADDR_1);
	}
	/* Move data from DM9000 Read received packet from RX SRAM */	
	data_ptr = (uu8 *)pdata_buf;
	for (i = 14; i < Rx_Len; i++) {
		*data_ptr++ = IORD(DM9000A_DAT_ADDR_1);
	}

	dm9000a_iow(DM9000A_IMR, 0x81); // 重新开启网卡中断接收
	return Rx_Len;
}


//==============================================================================================
// 初始化
void InitNic_1(uu8 * macaddr) 
{
	multimac_mcastFilter[0] = multimac_mcastFilter[1] = 0;

	ether_addrress[0] = macaddr[0];
	ether_addrress[1] = macaddr[1];
	ether_addrress[2] = macaddr[2];
	ether_addrress[3] = macaddr[3];
	ether_addrress[4] = macaddr[4];
	ether_addrress[5] = macaddr[5];
	
	dm9000a_init(); 	// 硬件初始化
}

猜你喜欢

转载自blog.csdn.net/KISSMonX/article/details/38302931
今日推荐