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

📄 halposdm9000a.c

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


/*
 * 修改记录:
 *	20060310	创建该文件。
 *	20040518	M4修正更新。
 *
 */

/**
 * @file	halPOSDM9000A.c
 * @brief
 *	<li>功能: 实现POSDM9000A设备的HAL,该HAL目前仅支持网络组件的DLL</li>
 * @date 	20060310
 */

/**************************** 引用部分 *****************************************/
#include <board.h>
#include <delta.h>
#include "halPOSDM9000A.h"

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

/**************************** 定义部分 *****************************************/
#define POSDM9000A_IOW( _port, _value)	\
		{						\
			*( volatile char * )(tpEtherDevDataTable->vbpPOSDM9000AAddr) = _port;\
			*( volatile char * )(tpEtherDevDataTable->vbpPOSDM9000AAddr + 1) = _value;\
		}
#define POSDM9000A_IOR( _port, _value)	\
		{						\
		*( volatile char * )(tpEtherDevDataTable->vbpPOSDM9000AAddr) = _port;\
		_value = *( volatile char * )(tpEtherDevDataTable->vbpPOSDM9000AAddr + 1);\
		}
		
/**************************** 实现部分 *****************************************/

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

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

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

    return retval;

}

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

/**
 * @brief
 *		关闭设备的中断。工作就是屏蔽在ChipIntEnable中使能的中断类型。
 *
 * @param[in] vpEtherDevData 设备数据块指针,该结构的类型由HAL定义。
 *
 * @return TRUE	成功(始终返回该值)。
 */
T_BOOL POSDM9000A_ChipIntDisable(T_VOID *vpEtherDevData)
{
	T_HAL_POSDM9000A_DEV_DATA *tpEtherDevDataTable = (T_HAL_POSDM9000A_DEV_DATA *)vpEtherDevData;
	
	POSDM9000A_IOW(IMR, 0x80);  //disable TX/RX interrupt mask
	rSRCPND = 0x4;		//清除 pending
	rINTPND = 0x4;

	return TRUE;
}

/**
 * @brief
 *	启动设备的运行,对设备进行基本初始化工作.主要工作包括:
 *	1.获取HAL为了驱动该设备所需要的系统资源,一般指内存空间;
 *	2.设置设备寄存器,让设备工作在正常状态下;
 *	3.注意该接口不要关心设备的中断开关状态。
 *
 * @param[in] pEtherDevData 设备数据块指针,该结构的类型由HAL定义。
 *
 * @return
 * 		FALSE 	失败
 *		TRUE	成功
 */
T_BOOL POSDM9000A_Start(T_VOID *vpEtherDevData)
{
	T_WORD port;
	T_WORD i;
	T_BYTE IoMode;
	T_UHWORD phyid1,phyid2;	
	T_HAL_POSDM9000A_DEV_DATA *tpEtherDevDataTable = (T_HAL_POSDM9000A_DEV_DATA *)vpEtherDevData;


	//重启设备
	POSDM9000A_IOW(NCR, 1);

	//延时,等待重启完毕,延时时间大约需10us
	for(i = 0; i< 1000; i++)
	{
		;
	}
	
	//初始化中断
	rGPFCON |= 0x30;
	rGPFCON &= 0xffef;
	rGPFUP |= 0x04;
	
	//下降延触发
	rEXTINT0 = rEXTINT0 & 0xfffff0ff;
	rEXTINT0 |= 0x200;
	
	//设置POSDM9000A上的中断,低电平触发
	POSDM9000A_IOW(0x39,0x1);

	//设置T_EiStatus结构	
	POSDM9000A_IOR(ISR, IoMode);
	tpEtherDevDataTable->tEiStatus.io_mode = IoMode >> 6;
	tpEtherDevDataTable->tEiStatus.reg0 = POSDM9000A_REG00;
	tpEtherDevDataTable->tEiStatus.reg5 = POSDM9000A_REG05;
	tpEtherDevDataTable->tEiStatus.reg8 = POSDM9000A_REG08;
	tpEtherDevDataTable->tEiStatus.reg9 = POSDM9000A_REG09;
	tpEtherDevDataTable->tEiStatus.rega = POSDM9000A_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;
	
	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;
	
		
	//初始化寄存器
	POSDM9000A_IOW(NCR, tpEtherDevDataTable->tEiStatus.reg0);
	POSDM9000A_IOW(TCR, 0);     			// TX Polling clear
	POSDM9000A_IOW(BPTR, 0x3f); 			// high water overflow threshold,Less 3Kb, 200us
	POSDM9000A_IOW(FCTR, tpEtherDevDataTable->tEiStatus.reg9);	// Rx Flow Control : High/Low Water
	POSDM9000A_IOW(FCR, tpEtherDevDataTable->tEiStatus.rega);	// Flow Control
	POSDM9000A_IOW(SMCR, 0);    			// Special Mode
	POSDM9000A_IOW(NSR, 0x2c);  			// clear TX status
	POSDM9000A_IOW(ISR, 0x0f);  			// Clear interrupt status
	
	POSDM9000A_IOW( PAR, tpEtherDevDataTable->tEiStatus.local_mac_address[0] );
	POSDM9000A_IOW( PAR+1, tpEtherDevDataTable->tEiStatus.local_mac_address[1] );
	POSDM9000A_IOW( PAR+2, tpEtherDevDataTable->tEiStatus.local_mac_address[2] );
	POSDM9000A_IOW( PAR+3, tpEtherDevDataTable->tEiStatus.local_mac_address[3] );
	POSDM9000A_IOW( PAR+4, tpEtherDevDataTable->tEiStatus.local_mac_address[4] );
	POSDM9000A_IOW( PAR+5, tpEtherDevDataTable->tEiStatus.local_mac_address[5] );
	
	//清除多播地址
	port = MAR;
	for(i = 0; i < 7; i++)
	{
		PhyRead(vpEtherDevData,port,0x00);
	    port++;
	}
	POSDM9000A_IOW(port,0x80);

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

	SetPHYMode(vpEtherDevData);					// Set PHY after set op_mode

	for(i = 0; i< 2000000; i++)
	{
		;
	}

	return TRUE;
}

/**
 * @brief
 *	使能设备中断。设备也许有多种类型的中断,网络组件只关心发送和接收中断而已
 *	其他中断类型的处理将由HAL本身负责解释并响应。所以此处使能的中断类型应该包括
 *	发送中断和接收中断,其他类型中断由HAL自行决定。
 *
 * @param[in] vpEtherDevData 设备数据块指针,该结构的类型由HAL定义。
 *
 * @return TRUE	成功(始终返回该值)。
 */
T_BOOL POSDM9000A_ChipIntEnable(T_VOID *vpEtherDevData)
{
	T_HAL_POSDM9000A_DEV_DATA *tpEtherDevDataTable = (T_HAL_POSDM9000A_DEV_DATA *)vpEtherDevData;

	POSDM9000A_IOW(RCR, POSDM9000A_REG05 | 1);	//RX enable
	POSDM9000A_IOW(IMR, POSDM9000A_REGFF);  	//Enable TX/RX interrupt mask
	rSRCPND = 0x04;						//clear the pending
	rINTPND = 0x04;

	return TRUE;
}

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

	if(tpEtherDevDataTable->tEiStatus.tx_pkt_cnt == 1)
	{
		do
    	{
			POSDM9000A_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
    	{
			POSDM9000A_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;
	POSDM9000A_IOW(IMR, 0x80);	//Disable all interrupt

    if(wKtLen < 60)
	{
		wKtLen = 60;
	}

	//data_ptr = bpKtBuf;
	*( volatile char * )(tpEtherDevDataTable->vbpPOSDM9000AAddr) = 0xf8;
	tmplen = wKtLen;	//BYTE mode
	for (i = 0; i < tmplen; i++)
	{
		*( volatile char * )(tpEtherDevDataTable->vbpPOSDM9000AAddr+1) = bpKtBuf[i];
    }

	if (tpEtherDevDataTable->tEiStatus.tx_pkt_cnt == 0)
	{
		tpEtherDevDataTable->tEiStatus.tx_pkt_cnt++;
		POSDM9000A_IOW(TXPLL, wKtLen & 0xff);	// Set TX length to POSDM9000A
    	POSDM9000A_IOW(TXPLH, (wKtLen >> 8) & 0xff);
		POSDM9000A_IOW(TCR, 0x1);    			// Cleared after TX complete
		delta_clock_get(DELTA_CLOCK_GET_TICKS_SINCE_BOOT, (void*)(&jiffies));
		POSDM9000A_IOR(ISR,ISR_STATUS);
		while((ISR_STATUS & 0x02) == 0)
			POSDM9000A_IOR(ISR, ISR_STATUS);
		POSDM9000A_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;
  	}

	POSDM9000A_IOW(IMR, POSDM9000A_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 POSDM9000A_GetIntType(T_VOID *vpEtherDevData, T_UWORD uwVector, T_WORD *wpIntInfo)
{
	T_WORD IntStatus;
	T_BYTE RegSave;
	T_UWORD  ret = 0;

	T_HAL_POSDM9000A_DEV_DATA *tpEtherDevDataTable = (T_HAL_POSDM9000A_DEV_DATA *)vpEtherDevData;

	//清除中断

	tpEtherDevDataTable->tEiStatus.interrupt = 1;
	POSDM9000A_IOW(IMR,0x80);				// Disable all interrupt
	POSDM9000A_IOR(POSDM9000A_REG00 ,RegSave);	// Save previous register address
	POSDM9000A_IOR(ISR, IntStatus);	  		// Got POSDM9000A interrupt status
	POSDM9000A_IOR(ISR, IntStatus);	  		// Got POSDM9000A interrupt status

	POSDM9000A_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;
	}

⌨️ 快捷键说明

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