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

📄 halrtl8139.c

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

/*
 * 修改记录:
 *	20060110	创建该文件。
 *
 */

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

/**************************** 引用部分 *****************************************/
#include "sysDM.h"
#include "sysDR.h"
#include "halx86pci.h"
#include "halRtl8139.h"


/*************************** 前向声明部分 ****************************************/
T_MODULE T_BOOL rtl8139_Probe( T_HAL_RTL8139_DEV_DATA * pEtherDevDataTable, T_WORD index );
T_MODULE void Rtl8139_TxTmo( T_HAL_RTL8139_DEV_DATA * pEtherDevDataTable );
T_MODULE int Rtl8139_Tx( T_HAL_RTL8139_DEV_DATA * pEtherDevDataTable );
T_MODULE void Rtl8139_InitRing( T_HAL_RTL8139_DEV_DATA * pEtherDevDataTable );
T_MODULE void Rtl8139_mCastAddrAdd(T_HAL_RTL8139_DEV_DATA * pEtherDevDataTable,	char *buf	);
T_MODULE void Rtl8139_mCastAddrDel(T_HAL_RTL8139_DEV_DATA * pEtherDevDataTable,	void *buf	);

/**************************** 实现部分 *****************************************/
/**
 * @brief
 *	  	确认设备的存在,对于需要动态获得系统参数的设备
 *  需要在此处把系统资源占用信息更新,如PCI设备的中断
 *  号和基地址。
 *
 * @param[in] pEtherDevData:设备数据块指针,该结构的类型由HAL定义。
 *
 * @return 成功返回TRUE;否则,返回FALSE。
 */
T_BOOL rtl8139_Find( T_VOID *pEtherDevData )
{

	T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
	T_WORD retval;
	int i;
    // 确认In82559的存在,更新配置表项

    retval = rtl8139_Probe( pEtherDevDataTable, pEtherDevDataTable->devIndex );
    for(i = 0; i < 6; i++)
    {
        BSP_InByte( pEtherDevDataTable->IoBaseAddr + R8139_IDR0 + i, pEtherDevDataTable->macaddr[i] );

    }

    if ( retval != TRUE )
    {
        return FALSE;
    }
    return TRUE;

}


/**
 * @brief
 *		该接口用来获取HAL管理该设备需要的资源(主要指内存)
 *	        HAL不应该再再别的地方进行资源的获取工作,该接口获得的资源将都被传给HAL中其他接口使用。
 *
 * @param[in] pEtherDevData:设备数据块指针,该结构的类型由HAL定义。
 *
 * @return 成功返回TRUE;否则,返回FALSE。
 */
T_BOOL rtl8139_GetResource( T_VOID *pEtherDevData )
{
	T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
	T_WORD Status = 0;
	/*
	* 申请发送以及接收缓存
	*/
	Status = fnDM_SemaphoreCreate (
				"RTL8139ETHER",
				1,
				DM_SIMPLE_BINARY_SEMAPHORE,
				DM_NO_PRIORITY,
				&pEtherDevDataTable->outbufmutex);
	if (Status != DM_SUCCESSFUL)
		return FALSE;

	pEtherDevDataTable->rxBufLen = (8192 << pEtherDevDataTable->rxBufSize);
	pEtherDevDataTable->tx_bufs = (unsigned char *)malloc(pEtherDevDataTable->txBufSize * NUM_TX_DESC);
	pEtherDevDataTable->rx_ring = (unsigned char *)malloc(pEtherDevDataTable->rxBufLen + 16); /*1536 for don't wrap option*/




	return TRUE;
}


/**
 * @brief
 *		释放HAL占用的资源(主要指在GetResource中获取到的资源)
 *
 * @param[in] pEtherDevData:设备数据块指针,该结构的类型由HAL定义。
 *
 * @return 成功返回TRUE;否则,返回FALSE。
 */
 T_BOOL rtl8139_ReleaseResource( T_VOID *pEtherDevData )
{
	T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
	free(pEtherDevDataTable->rx_ring);
   	free(pEtherDevDataTable->tx_bufs);

	return TRUE;
}


/**
 * @brief
 *	  	启动设备的运行,对设备进行基本初始化工作.主要工作包括:
 * 1.获取HAL为了驱动该设备所需要的系统资源,一般指内存空间
 * 2.设置设备寄存器,让设备工作在正常状态下
 * 3.注意该接口不要关心设备的中断开关状态。
 *
 * @param[in] pEtherDevData 设备数据块指针,该结构的类型由HAL定义。
 *
 * @return 成功返回TRUE;否则,返回FALSE。
 */

T_BOOL rtl8139_Start( T_VOID *pEtherDevData )
{
	T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
	T_UHWORD 		i = 0 ;
	T_WORD 				full_duplex = 0 ;
	T_UHWORD 		lpar = 0;
	T_BYTE			ioInVar;
	T_UHWORD		ioInUHword;

	BSP_OutByte( pEtherDevDataTable->IoBaseAddr + R8139_CR, 0x10 );


    // 初始化设备运行状态参数,注意,在此不应该涉及资源申请
	Rtl8139_InitRing( pEtherDevDataTable );

	// 检查设备是否已经完全复位
	for (i = 5000; i > 0; i--)
	{
		BSP_InByte( pEtherDevDataTable->IoBaseAddr + R8139_CR, ioInVar);
		if (( ioInVar & 0x10) == 0)
		{
			break;
		}
	}
	if(i<=0)
	{
		return FALSE;
	}

	BSP_InHWord( pEtherDevDataTable->IoBaseAddr + R8139_BMCR, ioInUHword);
	BSP_OutHWord( pEtherDevDataTable->IoBaseAddr + R8139_BMCR, ioInUHword | 0x1300);

	// 初始化MAC寄存器
	for (i = 0; i < 6; i++)
	{
		BSP_OutByte( pEtherDevDataTable->IoBaseAddr + R8139_IDR0+i, pEtherDevDataTable->macaddr[i]);
	}

	do
	{
		BSP_InHWord( pEtherDevDataTable->IoBaseAddr + R8139_BMSR, ioInUHword);
	}
	while (( ioInUHword & 0x20 ) == 0);

	// Must enable Tx/Rx before setting transfer thresholds!
	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);

	BSP_OutLong( pEtherDevDataTable->IoBaseAddr + R8139_TCR,(TX_DMA_BURST<<8)|0x03000000);

	full_duplex = 1;
	BSP_InHWord( pEtherDevDataTable->IoBaseAddr + R8139_ANLPAR, lpar);

	if ((lpar & 0x0100) == 0x0100 || (lpar & 0x00C0) == 0x0040)
	{
		full_duplex = 1;
	}
	else
	{
        full_duplex = 0;
	}

	BSP_OutByte( pEtherDevDataTable->IoBaseAddr + R8139_9346CR,0xC0);
	BSP_OutByte( pEtherDevDataTable->IoBaseAddr + R8139_CONFIG1,full_duplex ? 0x60 : 0x20);
	BSP_OutByte( pEtherDevDataTable->IoBaseAddr + R8139_9346CR,0x00);
	BSP_OutLong( pEtherDevDataTable->IoBaseAddr + R8139_RBSTART,(unsigned long)pEtherDevDataTable->rx_ring);

	// Start the chip's Tx and Rx process.
	BSP_OutLong( pEtherDevDataTable->IoBaseAddr + R8139_MPC,0);
	BSP_OutByte( pEtherDevDataTable->IoBaseAddr + R8139_CR,0x0c);/*enable rx and tx*/


	pEtherDevDataTable->interrupt = 0;

	// clear interrupt status register.if not done,receive buf will remain empty
	BSP_OutHWord( pEtherDevDataTable->IoBaseAddr + R8139_IMR,0x0000);
	BSP_OutHWord( pEtherDevDataTable->IoBaseAddr + R8139_ISR,0xffff);

	// Enable all known interrupts by setting the interrupt mask.

	BSP_OutHWord( pEtherDevDataTable->IoBaseAddr + R8139_IMR,
		PCIErr|PCSTimeout|RxUnderrun|RxOverflow|RxFIFOOver|TxErr|TxOK|RxErr|RxOK);

	// 延迟2秒,等待网卡和HUB或主机协商过程完成
	delta_task_wake_after(2000);

	return TRUE;
}



/**
 * @brief
 *	  	停止(或暂停)设备的运行,就是让该IO设备不能(正常)输入输出。
 *	该函数一般就是要设置DISABLE位,或者把该设备
 *	设置为内循环模式等。
 *
 * @param[in] pEtherDevData:设备数据块指针,该结构的类型由HAL定义。
 *
 * @return 成功返回TRUE;否则,返回FALSE。
 */
T_BOOL rtl8139_Stop( T_VOID *pEtherDevData )
{
	T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
	T_WORD rxerr = 0;



   	// Disable interrupts by clearing the interrupt mask.
   	BSP_OutHWord( pEtherDevDataTable->IoBaseAddr +R8139_IMR,0x0000);

   	// Stop the chip's Tx and Rx DMA processes.
   	BSP_OutByte( pEtherDevDataTable->IoBaseAddr +R8139_CR,0x00);

   	// Update the error counts.

	BSP_InLong( pEtherDevDataTable->IoBaseAddr  + R8139_MPC, rxerr);
   	BSP_OutLong( pEtherDevDataTable->IoBaseAddr +R8139_MPC,0);


   	//Put the chip in low-power mode.
   	BSP_OutByte( pEtherDevDataTable->IoBaseAddr +R8139_9346CR,0xC0);
   	BSP_OutByte( pEtherDevDataTable->IoBaseAddr +R8139_CONFIG1,0x03);


    return TRUE;
}

/**
 * @brief
 *	  	增加一个组播地址到该网卡
 *
 * @param[in] pEtherDevData: 设备数据块指针,该结构的类型由HAL定义。
 *
 * @param[in] macAddr:指向一个6字节的存储空间,内容为需要增加的组播MAC地址。
 *
 * @param[in] multiMacChian 指向一个组播地址链,该链上的组播地址应该都被设置进入该网卡.该链的结构是
 *				typedef struct ether_multi{
 *				char haddr[6];	//组播地址
 *				unsigned short emc_users;  //该组播地址的用户数,对于驱动,不需要关心该参数
 *				struct ether_multi * next;  //指向下一节点
 *				}ETHER_MULTI;
 *
 *				typedef struct macforhash{
 *				unsigned char macaddr[6];//要操作的组播MAC地址
 *				ETHER_MULTI * chainpointer;	//该设备需要设置的组播地址链
 *				}T_MACHASH;
 *				multiMacChian为 T_MACHASH 指针类型,该参数的使用是可选的.
 *				即,HAL中,增加组播地址的实现既可仅根据macaddr参数进行操作,
 *				也可以根据multiMacChain来全部重新设定网卡组播地址
 *
 * @return 成功返回TRUE;否则,返回FALSE。
 */
T_BOOL rtl8139_AddMultiAddr( T_VOID * pEtherDevData, T_CHAR *macAddr, T_VOID * multiMacChain)
{
	T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
	Rtl8139_mCastAddrAdd(pEtherDevDataTable,macAddr);
	return TRUE;
}

/**
 * @brief
 *	  	删除该网卡的一个组播地址
 *
 * @param[in] pEtherDevData: 设备数据块指针,该结构的类型由HAL定义。
 *
 * @param[in] macAddr:指向一个6字节的存储空间,内容为需要删除的组播MAC地址。
 *
 * @param[in] multiMacChian 指向一个组播地址链,该链上的组播地址应该都被设置进入该网卡.该链的结构是
 *				typedef struct ether_multi{
 *				char haddr[6];	//组播地址
 *				unsigned short emc_users;  //该组播地址的用户数,对于驱动,不需要关心该参数
 *				struct ether_multi * next;  //指向下一节点
 *				}ETHER_MULTI;
 *
 *				typedef struct macforhash{
 *				unsigned char macaddr[6];//要操作的组播MAC地址
 *				ETHER_MULTI * chainpointer;	//该设备需要设置的组播地址链
 *				}T_MACHASH;
 *				multiMacChian为 T_MACHASH 指针类型,该参数的使用是可选的.
 *				即,HAL中,增加组播地址的实现既可仅根据macaddr参数进行操作,
 *				也可以根据multiMacChain来全部重新设定网卡组播地址
 *
 * @return 成功返回TRUE;否则,返回FALSE。
 */
T_BOOL rtl8139_DelMultiAddr( T_VOID * pEtherDevData, T_CHAR *macAddr, T_VOID * multiMacChain)
{
	T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
	Rtl8139_mCastAddrDel(pEtherDevDataTable,multiMacChain);
	return TRUE;
}


/**
 * @brief
 *	  	发送数据包,把从DLL传来的数据包发送出去。
 *
 * @param[in] pEtherDevData: 设备数据块指针,该结构的类型由HAL定义。
 * @param[in] pktBuf:数据包所在的缓存指针。
 * @param[in] pktLen:数据包大小。
 *
 * @return 成功返回TRUE;否则,返回FALSE。
 */
T_BOOL rtl8139_SendPkt( T_VOID *pEtherDevData, T_CHAR * pktBuf, T_WORD pktLen )
{
	T_HAL_RTL8139_DEV_DATA *pEtherDevDataTable = (T_HAL_RTL8139_DEV_DATA *)pEtherDevData;
	unsigned int 			i = 0;
	int 			j = 0;
	int				txbusy = pEtherDevDataTable->txbusy;
	int				txentry = pEtherDevDataTable->txentry;

	// 用tbusy做互斥
   	if( pEtherDevDataTable->tx_full )
   	{
   			if(fnDM_SemaphoreObtain (pEtherDevDataTable->outbufmutex, DM_WAIT, 8000) != DM_SUCCESSFUL )

⌨️ 快捷键说明

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