📄 halrtl8139.c
字号:
{
//if((txbusy & 0x0f) == 0x0f)
//{
// 处理超时,复位设备
Rtl8139_TxTmo( pEtherDevDataTable );
return FALSE;
//}
}
}
// 计算下一个发送描述块的地址
txbusy |= (1<<txentry);
i = txentry + 1;
i = (i)%NUM_TX_DESC;
if( txbusy & (1<<i) )
{
pEtherDevDataTable->tx_full = 1;
pEtherDevDataTable->txentry = i;
}
else
{
pEtherDevDataTable->txentry = i;
}
pEtherDevDataTable->txbusy = txbusy;
memcpy(pEtherDevDataTable->tx_buf[txentry], pktBuf, pktLen);
BSP_OutLong( pEtherDevDataTable->IoBaseAddr + R8139_TSAD0+txentry*4,(unsigned long)(pEtherDevDataTable->tx_buf[txentry]));
BSP_OutLong( pEtherDevDataTable->IoBaseAddr +R8139_TSD0+txentry*4,(pEtherDevDataTable->tx_flag )|(pktLen >= ETH_ZLEN ? pktLen : ETH_ZLEN));
return TRUE;
}
/**
* @brief
* 使能设备中断。设备也许有多种类型的中断,网络组件只关心发送和接收中断而已
* 其他中断类型的处理将由HAL本身负责解释并响应。所以此处使能的中断类型应该包括
* 发送中断和接收中断,其他类型中断由HAL自行决定。
*
* @param[in] pEtherDevData:设备数据块指针,该结构的类型由HAL定义。
*
* @return 成功返回TRUE;否则,返回FALSE。
*/
T_BOOL rtl8139_ChipIntEnable( T_VOID *pEtherDevData )
{
T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
// 清除现有中断标志位,置使能中断掩码
BSP_OutHWord(pEtherDevDataTable->IoBaseAddr+R8139_IMR,
PCIErr|PCSTimeout|RxUnderrun|RxOverflow|RxFIFOOver|TxErr|TxOK|RxErr|RxOK);
//BSP_OutHWord( pEtherDevDataTable->IoBaseAddr + R8139_ISR, 0xffff );
return TRUE;
}
/**
* @brief
* 关闭设备的中断。工作就是屏蔽在ChipIntEnable中使能的中断类型。
*
* @param[in] pEtherDevData 设备数据块指针,该结构的类型由HAL定义。
*
* @return 成功返回TRUE;否则,返回FALSE。
*/
T_BOOL rtl8139_ChipIntDisable( T_VOID *pEtherDevData )
{
T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
// 设置中断屏蔽
BSP_OutHWord( pEtherDevDataTable->IoBaseAddr + R8139_IMR, 0x0000 );
return TRUE;
}
/**
* @brief
* 获取中断类型。当设备发生中断时,该接口将被调用。
*
* @param[in] pEtherDevData :设备数据块指针,该结构的类型由HAL定义。
* @param[in] vector:产生中断的中断向量。
* @param[out] *intInfo: 设备的中断信息,当返回的中断类型中包括"其他中断类型"
时,该参数将被传给HandleOtherIntType的HAL接口。
*
* @return 当发生多种中断类型时,把如下的返回值采用‘位或’运算后再返回。
* DEV_NO_INTERRUPT:该设备没有发生中断
* DEV_INT_HAD_HANDLED:设备发生了中断,但已经被处理了
* DEV_RECEIVE_INTERRUPT:设备发生了接收中断
* DEV_SENDOVER_INTERRUPT:设备发生了发生中断
* DEV_OHER_INTTYPE: 设备发生了其他的中断类型
*/
T_UWORD rtl8139_GetIntType( T_VOID *pEtherDevData, T_UWORD vector, T_WORD *intInfo )
{
T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
int ISRstatus = 0;
T_UWORD ret = 0;
T_UWORD ioHWord;
// 查询中断标志
BSP_InHWord( pEtherDevDataTable->IoBaseAddr +R8139_ISR, ISRstatus);
// 清除中断标志
BSP_OutHWord( pEtherDevDataTable->IoBaseAddr +R8139_ISR,0xffff);
//Acknowledge all of the current interrupt sources ASAP.
if ((ISRstatus & (PCIErr|PCSTimeout|RxUnderrun|RxOverflow|RxFIFOOver
|TxErr|TxOK|RxErr|RxOK)) == 0)
{
return DEV_NO_INTERRUPT;
}
//优先处理故障中断
if (ISRstatus & RxOverflow)
{
BSP_InHWord( pEtherDevDataTable->IoBaseAddr + R8139_CBR, ioHWord);
pEtherDevDataTable->cur_rx = ioHWord % pEtherDevDataTable->rxBufLen;
BSP_OutHWord( pEtherDevDataTable->IoBaseAddr +R8139_CAPR,pEtherDevDataTable->cur_rx-16);
ret |= DEV_INT_HAD_HANDLED;
}
if (ISRstatus & (RxOK|RxUnderrun|RxOverflow/*| RxErr*/|RxFIFOOver))/* Rx interrupt */
{
ret |= DEV_RECEIVE_INTERRUPT;
}
if (ISRstatus & (TxOK | TxErr))
{
Rtl8139_Tx( pEtherDevDataTable );
//ret |= DEV_SENDOVER_INTERRUPT;
}
*intInfo = ISRstatus;
return ret;
}
/**
* @brief
* 获取设备当前接收到的数据包长度。当设备发生接收中断时,该接口将被调用。
*
* @param[in] pEtherDevData: 设备数据块指针,该结构的类型由HAL定义。
* @param[out] pktLen:指针,指向数据包的长度
*
* @return 成功返回TRUE;否则,返回FALSE。
*/
T_BOOL rtl8139_GetPktLen( T_VOID *pEtherDevData, T_WORD *pktLen)
{
T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
unsigned char *rx_ring = NULL;
unsigned short cur_rx = 0;
unsigned long rx_status;
int ring_offset = 0;
int rx_size = 0;
T_WORD count = 0;
T_BYTE ioByte;
T_HWORD ioHWord;
rx_ring = pEtherDevDataTable->rx_ring;
cur_rx = pEtherDevDataTable->cur_rx;
BSP_InByte( pEtherDevDataTable->IoBaseAddr + R8139_CR, ioByte);
if( (ioByte & 1)==0 )
{
ring_offset = cur_rx % pEtherDevDataTable->rxBufLen;
rx_status = *(unsigned long*)(rx_ring + ring_offset);
rx_size = rx_status >> 16;
if (!(rx_status&(RxBadSymbol|RxRunt|RxTooLong|RxCRCErr|RxBadAlign)))
{
// 接收到数据
if( ( rx_size >= 64 ) && (rx_size <= 1518 ) )
{
count = rx_size-4;
}
else
{
BSP_InHWord( pEtherDevDataTable->IoBaseAddr +R8139_CBR, ioHWord);
cur_rx = ioHWord % pEtherDevDataTable->rxBufLen;
BSP_OutHWord( pEtherDevDataTable->IoBaseAddr +R8139_CAPR,cur_rx-16);
pEtherDevDataTable->cur_rx = cur_rx ;
count = 0;
}
}
else
{
// 接收错误,丢弃所有数据包
pEtherDevDataTable->cur_rx = 0;
BSP_OutByte( pEtherDevDataTable->IoBaseAddr +R8139_CR,0x04); /*enable tx*/
BSP_OutByte( pEtherDevDataTable->IoBaseAddr +R8139_CR,0x0c); /*enable tx and rx*/
BSP_OutLong( pEtherDevDataTable->IoBaseAddr +R8139_RCR,
(RX_FIFO_THRESH<<13)|(pEtherDevDataTable->rxBufSize<<11)|(RX_DMA_BURST<<8)|RX_OPTION);
cur_rx += rx_size + 4;
cur_rx = (cur_rx + 3) & ~3;
BSP_OutHWord( pEtherDevDataTable->IoBaseAddr +R8139_CAPR,cur_rx-16);
pEtherDevDataTable->cur_rx = cur_rx ;
count = 0;
}
}
else
{
return FALSE;
}
*pktLen = count;
return TRUE;
}
/**
* @brief
* 获取设备当前接收到的数据包的数据。当设备发生接收中断,
* 且GetPktLen接口返回的数据包长度大于0时该接口将被调用。
*
* @param[in] pEtherDevData:设备数据块指针,该结构的类型由HAL定义。
* @param[in] pktLen:数据包的长度 ,该参数即GetPktLen的返回值。
*
* @return 成功返回TRUE;否则,返回FALSE。
*/
T_BOOL rtl8139_GetPktData( T_VOID *pEtherDevData, T_CHAR * pktBuf, T_WORD pktLen )
{
T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
unsigned char *rx_ring = NULL;
unsigned short cur_rx = 0;
int ring_offset = 0;
int semi_count = 0;
int semi_count2 = 0;
rx_ring = pEtherDevDataTable->rx_ring;
cur_rx = pEtherDevDataTable->cur_rx;
ring_offset = cur_rx % pEtherDevDataTable->rxBufLen;
// 拷贝数据
if (ring_offset+pktLen > pEtherDevDataTable->rxBufLen)
{
semi_count = pEtherDevDataTable->rxBufLen - ring_offset - 4;
semi_count2 = pktLen - semi_count;
if(semi_count>0)
{
memcpy(pktBuf , &rx_ring[ring_offset + 4],semi_count);
memcpy(pktBuf+semi_count , rx_ring,semi_count2);
}
else
memcpy(pktBuf , &rx_ring[-semi_count],pktLen);
}
else
memcpy(pktBuf, &rx_ring[ring_offset + 4],pktLen);
// 更新读写指针
cur_rx += pktLen + 8;
cur_rx = (cur_rx + 3) & ~3;
BSP_OutHWord(pEtherDevDataTable->IoBaseAddr+R8139_CAPR,cur_rx-16);
// 更新控制状态
pEtherDevDataTable->cur_rx = cur_rx ;
return TRUE;
}
/**
* @brief
* 处理其他的中断类型。中断类型参数intInfo即在GetIntType中返回的中断
* 状态信息。该信息由HAL自己负责定义和解释。
*
* @param[in] pEtherDevData:设备数据块指针,该结构的类型由HAL定义。
* @param[in] intInfo:中断状态信息。
*
* @return
* FALSE 失败
* TRUE 成功
*/
T_BOOL rtl8139_HandleOtherIsrType( T_VOID *pEtherDevData, T_WORD intInfo)
{
T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
if (intInfo & (TxOK | TxErr))
{
//Rtl8139_Tx( pEtherDevDataTable );
}
return TRUE;
}
/**
* @brief
* 获取设备的MAC地址。
*
* @param[in] pEtherDevData:设备数据块指针,该结构的类型由HAL定义。
* @param[out] macAddr:存放MAC地址的缓存。
*
* @return 成功返回TRUE;否则,返回FALSE。
*/
T_BOOL rtl8139_GetMacAddr( T_VOID *pEtherDevData, T_CHAR *macAddr )
{
T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
T_WORD i = 0;
// Bring the chip out of low-power mode.
BSP_OutByte(pEtherDevDataTable->IoBaseAddr + R8139_CONFIG1,0x00);
for(i = 0; i < 6; i++)
{
BSP_InByte( pEtherDevDataTable->IoBaseAddr + R8139_IDR0 + i, pEtherDevDataTable->macaddr[i] );
}
memcpy(macAddr,pEtherDevDataTable->macaddr,6);
return TRUE;
}
/**
* @brief
* 设置设备的MAC地址。
*
* @param[in] pEtherDevData:设备数据块指针,该结构的类型由HAL定义。
* @param[out] macAddr:存放MAC地址的缓存。
*
* @return 成功返回TRUE;否则,返回FALSE。
*/
T_BOOL rtl8139_SetMacAddr( T_VOID *pEtherDevData, T_CHAR *macAddr )
{
T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
T_WORD i = 0;
// Bring the chip out of low-power mode.
BSP_OutByte(pEtherDevDataTable->IoBaseAddr + R8139_CONFIG1,0x00);
BSP_OutByte( pEtherDevDataTable->IoBaseAddr + R8139_9346CR, 0xc0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -