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

📄 haldm9000.c

📁 包含8139
💻 C
📖 第 1 页 / 共 2 页
字号:

/*
 * 修改记录:
 *	20060310	创建该文件。
 *	20040518	M4修正更新。		
 *
 */ 
 
/**
 * @file	halDM9000.c
 * @brief
 *	<li>功能: 实现DM9000设备的HAL,该HAL目前仅支持网络组件的DLL</li>
 * @date 	20060310
 */
 
/**************************** 引用部分 *****************************************/
#include <board.h>
#include <delta.h>
#include "halDM9000.h"

/*************************** 前向声明部分 ****************************************/
T_MODULE T_VOID PhyRead(T_VOID *vpEtherDevData, T_WORD wReg, T_UHWORD *uhpValue);
T_MODULE T_VOID PhyWrite(T_VOID *vpEtherDevData, T_WORD wReg, T_UHWORD uhValue);
T_MODULE T_VOID SetPHYMode(T_VOID *vpEtherDevData);
T_MODULE T_BOOL Probe(T_HAL_DM9000_DEV_DATA *vpEtherDevData);

/**************************** 定义部分 *****************************************/
#define DM9000_IOW( _port, _value)	\
		{						\
			*( volatile char * )(tpEtherDevDataTable->vbpDM9000Addr) = _port; 	\
			*( volatile char * )(tpEtherDevDataTable->vbpDM9000Addr+4) = _value;	\
		}
#define DM9000_IOR( _port, _value)	\
		{						\
		*( volatile char * )(tpEtherDevDataTable->vbpDM9000Addr) = _port;		\
		_value = *( volatile char * )(tpEtherDevDataTable->vbpDM9000Addr+4);		\
		}



/**************************** 实现部分 *****************************************/

/**
 * @brief
 *	  	确认设备的存在,对于需要动态获得系统参数的设备
 *    需要在此处把系统资源占用信息更新。
 *
 * @param[in] vpEtherDevData 设备数据块指针,该结构的类型由HAL定义。
 * 
 * @return	TRUE	成功	。
 *			FALSE	失败。				
 */
T_BOOL DM9000_Find(T_VOID *vpEtherDevData)
{

	T_HAL_DM9000_DEV_DATA *tpEtherDevDataTable = (T_HAL_DM9000_DEV_DATA *)vpEtherDevData;
	T_WORD retval;

    // 确认DM9000的存在,更新配置表项
    retval = Probe(tpEtherDevDataTable);

    return retval;

}

/**
 * @brief
 *		该接口用来获取HAL管理该设备需要的资源(主要指内存)
 *	   HAL不应该再再别的地方进行资源的获取工作,该接口获得的资源将都被传给HAL中其他接口使用。
 *
 * @param[in] vpEtherDevData 设备数据块指针,该结构的类型由HAL定义。
 * 
 * @return TRUE	成功	(始终返回该值)。	
 */
T_BOOL DM9000_GetResource(T_VOID *vpEtherDevData)
{
	return TRUE;
}

/**
 * @brief
 *		关闭设备的中断。工作就是屏蔽在ChipIntEnable中使能的中断类型。
 *
 * @param[in] vpEtherDevData 设备数据块指针,该结构的类型由HAL定义。
 * 
 * @return TRUE	成功(始终返回该值)。		
 */
T_BOOL DM9000_ChipIntDisable(T_VOID *vpEtherDevData)
{ 
	T_HAL_DM9000_DEV_DATA *tpEtherDevDataTable = (T_HAL_DM9000_DEV_DATA *)vpEtherDevData;
	
	rEXTINT &= 0xffff8fff;
	rEXTINT |= 0x1000;		//设置 EXINT3 为高位
	DM9000_IOW(IMR, 0x80);  //disable TX/RX interrupt mask
	rI_ISPC = 0x400000;		//清除 pending
	
	return TRUE;
}

/**
 * @brief
 *		启动设备的运行,对设备进行基本初始化工作.主要工作包括:
 *	1.获取HAL为了驱动该设备所需要的系统资源,一般指内存空间;
 *	2.设置设备寄存器,让设备工作在正常状态下;
 *	3.注意该接口不要关心设备的中断开关状态。
 *
 * @param[in] pEtherDevData 设备数据块指针,该结构的类型由HAL定义。
 * 
 * @return 
 * 		FALSE 	失败
 *		TRUE	成功		
 */
T_BOOL DM9000_Start(T_VOID *vpEtherDevData)
{
	T_WORD port;
	T_WORD i;
	T_BYTE IoMode;
	T_UHWORD phyid1,phyid2;
	T_HAL_DM9000_DEV_DATA *tpEtherDevDataTable = (T_HAL_DM9000_DEV_DATA *)vpEtherDevData;
	
	/*设置MAC地址*/
	
	tpEtherDevDataTable->tEiStatus.local_mac_address[0] = tpEtherDevDataTable->mac0;
	tpEtherDevDataTable->tEiStatus.local_mac_address[1] = tpEtherDevDataTable->mac1;
	tpEtherDevDataTable->tEiStatus.local_mac_address[2] = tpEtherDevDataTable->mac2;
	tpEtherDevDataTable->tEiStatus.local_mac_address[3] = tpEtherDevDataTable->mac3;
	tpEtherDevDataTable->tEiStatus.local_mac_address[4] = tpEtherDevDataTable->mac4;
	tpEtherDevDataTable->tEiStatus.local_mac_address[5] = tpEtherDevDataTable->mac5;
	
	//重启设备
	DM9000_IOW(NCR, 1); 			
	
	//延时,等待重启完毕,延时时间大约需10us
	for(i = 0; i< 1000; i++)
	{
		;		
	} 

	//设置T_EiStatus结构
	DM9000_IOR(ISR, IoMode);
	tpEtherDevDataTable->tEiStatus.io_mode = IoMode >> 6;
	tpEtherDevDataTable->tEiStatus.reg0 = DM9000_REG00;
	tpEtherDevDataTable->tEiStatus.reg5 = DM9000_REG05;
	tpEtherDevDataTable->tEiStatus.reg8 = DM9000_REG08;
	tpEtherDevDataTable->tEiStatus.reg9 = DM9000_REG09;
	tpEtherDevDataTable->tEiStatus.rega = DM9000_REG0A;
	tpEtherDevDataTable->tEiStatus.interrupt = 0;
	tpEtherDevDataTable->tEiStatus.queue_pkt_len = 0;
	tpEtherDevDataTable->tEiStatus.trans_start = 0;
	tpEtherDevDataTable->tEiStatus.tx_pkt_cnt = 0;
	tpEtherDevDataTable->tEiStatus.tbusy = 0;
	tpEtherDevDataTable->tEiStatus.start = 1;
	
	// 初始化寄存器
	DM9000_IOW(NCR, tpEtherDevDataTable->tEiStatus.reg0);
	DM9000_IOW(TCR, 0);     			// TX Polling clear
	DM9000_IOW(BPTR, 0x3f); 			// high water overflow threshold,Less 3Kb, 200us
	DM9000_IOW(FCTR, tpEtherDevDataTable->tEiStatus.reg9);	// Rx Flow Control : High/Low Water
	DM9000_IOW(FCR, tpEtherDevDataTable->tEiStatus.rega);	// Flow Control
	DM9000_IOW(SMCR, 0);    			// Special Mode
	DM9000_IOW(NSR, 0x2c);  			// clear TX status
	DM9000_IOW(ISR, 0x0f);  			// Clear interrupt status

	DM9000_IOW( PAR, tpEtherDevDataTable->tEiStatus.local_mac_address[0] );
	DM9000_IOW( PAR+1, tpEtherDevDataTable->tEiStatus.local_mac_address[1] );
	DM9000_IOW( PAR+2, tpEtherDevDataTable->tEiStatus.local_mac_address[2] );
	DM9000_IOW( PAR+3, tpEtherDevDataTable->tEiStatus.local_mac_address[3] );
	DM9000_IOW( PAR+4, tpEtherDevDataTable->tEiStatus.local_mac_address[4] );
	DM9000_IOW( PAR+5, tpEtherDevDataTable->tEiStatus.local_mac_address[5] );

	//清除多播地址
	port = MAR;
	for(i = 0; i < 7; i++)
	{
		DM9000_IOW(port,0x00);
	    port++;
	}
	DM9000_IOW(port,0x80);

	//read internal PHY id and init PHY
	PhyRead(vpEtherDevData, 0x02, &phyid1);
	PhyRead(vpEtherDevData, 0x03, &phyid2);
	if((phyid1 != 0x181) || (phyid2 != 0xb8c0))
	{
		return FALSE;
	}

	SetPHYMode(vpEtherDevData);					// Set PHY after set op_mode
	
	//延时,等待网卡和HUB或主机协商过程完成
	for(i = 0; i< 2000000; i++)
	{
		; 
	}
	
	return TRUE;
}

/**
 * @brief
 *		使能设备中断。设备也许有多种类型的中断,网络组件只关心发送和接收中断而已
 *	其他中断类型的处理将由HAL本身负责解释并响应。所以此处使能的中断类型应该包括
 *	发送中断和接收中断,其他类型中断由HAL自行决定。
 *
 * @param[in] vpEtherDevData 设备数据块指针,该结构的类型由HAL定义。
 * 
 * @return TRUE	成功(始终返回该值)。		
 */
T_BOOL DM9000_ChipIntEnable(T_VOID *vpEtherDevData)
{
	T_HAL_DM9000_DEV_DATA *tpEtherDevDataTable = (T_HAL_DM9000_DEV_DATA *)vpEtherDevData;
	
	DM9000_IOW(RCR, DM9000_REG05 | 1);	//RX enable
	DM9000_IOW(IMR, DM9000_REGFF);  	//Enable TX/RX interrupt mask
	rI_ISPC = 0x400000;					//clear the pending

	return TRUE;
}

/**
 * @brief
 *	  	发送数据包,把从DLL传来的数据包发送出去。
 *
 * @param[in] vpEtherDevData	设备数据块指针,该结构的类型由HAL定义。
 * @param[in] bpKtBuf		数据包所在的缓存指针。
 * @param[in] wKtLen		数据包大小。
 * 
 * @return 
 * 		FALSE 	失败
 *		TRUE	成功		
 */
T_BOOL DM9000_SendPkt(T_VOID *vpEtherDevData, T_CHAR *bpKtBuf, T_WORD wKtLen)
{
	T_WORD tmplen,i;
	T_WORD wait = 0;
	T_WORD TCR_Status;
	T_WORD ISR_STATUS;
    T_UHWORD *data_ptr;
    T_UDWORD jiffies;
	T_UHWORD phyid1,phyid2;
	T_HAL_DM9000_DEV_DATA *tpEtherDevDataTable = (T_HAL_DM9000_DEV_DATA *)vpEtherDevData;

	if(tpEtherDevDataTable->tEiStatus.tx_pkt_cnt == 1)
	{
		do
    	{
			DM9000_IOR(TCR, TCR_Status);
			wait++;

		}while((TCR_Status & 0x01) && (wait <= 500000));

		if(TCR_Status & 0x01)
		{
			PhyRead(vpEtherDevData, 0x02, &phyid1);
			PhyRead(vpEtherDevData, 0x03, &phyid2);

			return FALSE;
		}
	}

	if((tpEtherDevDataTable->tEiStatus.tbusy != 0) || (tpEtherDevDataTable->tEiStatus.tx_pkt_cnt > 1))
    {
		do
    	{
			DM9000_IOR(TCR, TCR_Status);
			wait++;

		}while((TCR_Status & 0x01) && (wait <= 500000));


		if(TCR_Status & 0x01)
		{
			delta_clock_get(DELTA_CLOCK_GET_TICKS_SINCE_BOOT, (void*)(&jiffies));
			if (tpEtherDevDataTable->tEiStatus.trans_start && ((jiffies - tpEtherDevDataTable->tEiStatus.trans_start) > DMFE_TX_TIMEOUT))
			{
				tpEtherDevDataTable->tEiStatus.stat.tx_errors++;
				tpEtherDevDataTable->tEiStatus.tbusy = 0;
				tpEtherDevDataTable->tEiStatus.trans_start = 0;
				return FALSE;
			}
		}
		tpEtherDevDataTable->tEiStatus.tbusy = 1;

		return FALSE;
	}

	tpEtherDevDataTable->tEiStatus.tbusy = 1;
	DM9000_IOW(IMR, 0x80);	//Disable all interrupt
	
    if(wKtLen < 60)
	{
		wKtLen = 60;
	}
	
	data_ptr = (T_UHWORD *)bpKtBuf;
	*(( T_BYTE * )(tpEtherDevDataTable->vbpDM9000Addr)) = 0xf8;
	tmplen = (wKtLen + 1) / 2;	//Word mode
	for (i = 0; i < tmplen; i++)
	{
		*((T_HWORD *)(tpEtherDevDataTable->vbpDM9000Addr+4)) = data_ptr[i];
    }
    
	if (tpEtherDevDataTable->tEiStatus.tx_pkt_cnt == 0)
	{
		tpEtherDevDataTable->tEiStatus.tx_pkt_cnt++;
		DM9000_IOW(TXPLL, wKtLen & 0xff);	// Set TX length to DM9000
    	DM9000_IOW(TXPLH, (wKtLen >> 8) & 0xff);
		DM9000_IOW(TCR, 0x1);    			// Cleared after TX complete
		delta_clock_get(DELTA_CLOCK_GET_TICKS_SINCE_BOOT, (void*)(&jiffies));
		DM9000_IOR(ISR,ISR_STATUS);
		while((ISR_STATUS & 0x02) == 0)
			DM9000_IOR(ISR, ISR_STATUS);
		DM9000_IOW(ISR , 0x02);
		tpEtherDevDataTable->tEiStatus.tx_pkt_cnt--;
		tpEtherDevDataTable->tEiStatus.tbusy = 0;
    	tpEtherDevDataTable->tEiStatus.trans_start = jiffies;
  	}
    else
  	{
		tpEtherDevDataTable->tEiStatus.tx_pkt_cnt++;
	  	tpEtherDevDataTable->tEiStatus.queue_pkt_len = wKtLen;

    }
    
    if (tpEtherDevDataTable->tEiStatus.tx_pkt_cnt == 1)
  	{
		tpEtherDevDataTable->tEiStatus.tbusy  = 0;
  	}
  	
	DM9000_IOW(IMR, DM9000_REGFF);
	
	return TRUE;
}

/**
 * @brief
 *		获取中断类型。当设备发生中断时,该接口将被调用。
 *
 * @param[in]	vpEtherDevData	设备数据块指针,该结构的类型由HAL定义。
 * @param[in]	uwVector		产生中断的中断向量。
 * @param[out]	*wpIntInfo		设备的中断信息,当返回的中断类型中包括"其他中断类型"
								时,该参数将被传给HandleOtherIntType的HAL接口。
 *
 * @return  当发生多种中断类型时,把如下的返回值采用‘位或’运算后再返回。
 * 		DEV_NO_INTERRUPT		该设备没有发生中断。
 *		DEV_INT_HAD_HANDLED		设备发生了中断,但已经被处理了。
 *      DEV_RECEIVE_INTERRUPT	设备发生了接收中断。
 *		DEV_SENDOVER_INTERRUPT	设备发生了发生中断。
 *		DEV_OHER_INTTYPE		设备发生了其他的中断类型。
 */
T_UWORD DM9000_GetIntType(T_VOID *vpEtherDevData, T_UWORD uwVector, T_WORD *wpIntInfo)
{
	T_WORD IntStatus;
	T_BYTE RegSave;
	T_UWORD  ret = 0;
	T_HAL_DM9000_DEV_DATA *tpEtherDevDataTable = (T_HAL_DM9000_DEV_DATA *)vpEtherDevData;
	
	//清除中断
	rI_ISPC = 0x400000;
	
	tpEtherDevDataTable->tEiStatus.interrupt = 1;
	DM9000_IOW(IMR,0x80);				// Disable all interrupt
	DM9000_IOR(DM9000_REG00 ,RegSave);	// Save previous register address
	DM9000_IOR(ISR, IntStatus);	  		// Got DM9000 interrupt status	
	DM9000_IOR(ISR, IntStatus);	  		// Got DM9000 interrupt status
	
	DM9000_IOW(ISR, IntStatus);
		
	if ((IntStatus & 0x0f) == 0)
  	{
		return DEV_NO_INTERRUPT;
	}
		
	if (IntStatus & 1)
	{
		ret |= DEV_RECEIVE_INTERRUPT;
	}
	if (IntStatus & 2)
	{
		ret |= DEV_INT_HAD_HANDLED;
	}
	if (IntStatus & 4)
	{
		ret |= DEV_INT_HAD_HANDLED;
	}
	if (IntStatus & 8)
	{
		ret |= DEV_INT_HAD_HANDLED;
	}
	 
	tpEtherDevDataTable->tEiStatus.interrupt = 0;    		// release interrupt lock
	DM9000_IOW(IMR, DM9000_REGFF);		// Re-enable interrupt mask

⌨️ 快捷键说明

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