📄 halposdm9000a.c
字号:
/*
* 修改记录:
* 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 + -