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

📄 rtl8139.c

📁 Realtek8139小端口网卡驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
2004.12  第十项目小组 
主编:王翔 徐隽
协助:卢坚 夏亮 傅佳伟  郑皓 黄君炜
测试:王弥 
Rtl8139 根据 Win2000 DDK提供的Network Samples框架基础上进行编码 

  (声明:本驱动程序仅用于学习、探索、实践计算机网络相关知识之用。
请勿在未征得本小组同意的情况下随意传播。对使用本程序可能造成的
硬件问题本小组概不负责。也请勿将它用于学习之外的任何用途,本小组
对此种行为可能造成的不良后果概不负责。)                                          
      
****************************************************************************/

/****************************************************************************
模块名称:
    rtl8139.c

模块功能:
	入口函数,初始化设备,停止,重置设备等基本操作

开发环境:
    WinDDK XP 
	Visual C++6.0
    Driver Studio 3.1
*****************************************************************************/

#define	NDIS_WDM 1
#define NDIS_MINIPORT_DRIVER
#define NDIS50_MINIPORT   1 //NDIS版本5.0

#include "ndis.h"
#include "rtl8139hw.h"
#include "rtl8139sw.h"



#if DBG
#define STATIC
#else
#define STATIC static
#endif

//
// 进行Debug调试的预定义 
//
#if DBG

//
// 默认调试模式
//

ULONG RTL8139DebugFlag =0x11111111;

#define RTL8139_LOG_SIZE 256
UCHAR RTL8139LogBuffer[RTL8139_LOG_SIZE]={0};
UINT RTL8139LogLoc = 0;

extern
VOID
RTL8139Log(UCHAR c) {

    RTL8139LogBuffer[RTL8139LogLoc++] = c;

	RTL8139LogBuffer[(RTL8139LogLoc + 4) % RTL8139_LOG_SIZE] = '\0';

	if (RTL8139LogLoc >= RTL8139_LOG_SIZE)
		RTL8139LogLoc = 0;
}

#endif


PRTL8139_ADAPTER			g_adapter;//全局变量,用来表示网卡本身这个数据结构
PDEVICE_OBJECT      g_deviceObject;


NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
    NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);//被内存分配函数调用时可以取得的最高物理地址位

DRIVER_BLOCK RTL8139MiniportBlock={0};

//
// 网卡支持的OID的值
//
STATIC UINT RTL8139SupportedOids[] = {
    OID_GEN_SUPPORTED_LIST,
    OID_GEN_HARDWARE_STATUS,
    OID_GEN_MEDIA_SUPPORTED,
    OID_GEN_MEDIA_IN_USE,
    OID_GEN_MAXIMUM_LOOKAHEAD,
    OID_GEN_MAXIMUM_FRAME_SIZE,
    OID_GEN_MAXIMUM_TOTAL_SIZE,
    OID_GEN_MAC_OPTIONS,
    OID_GEN_PROTOCOL_OPTIONS,
    OID_GEN_LINK_SPEED,
    OID_GEN_TRANSMIT_BUFFER_SPACE,
    OID_GEN_RECEIVE_BUFFER_SPACE,
    OID_GEN_TRANSMIT_BLOCK_SIZE,
    OID_GEN_RECEIVE_BLOCK_SIZE,
    OID_GEN_VENDOR_DESCRIPTION,
    OID_GEN_VENDOR_ID,
    OID_GEN_DRIVER_VERSION,
    OID_GEN_CURRENT_PACKET_FILTER,
    OID_GEN_CURRENT_LOOKAHEAD,
    OID_GEN_XMIT_OK,
    OID_GEN_RCV_OK,
    OID_GEN_XMIT_ERROR,
    OID_GEN_RCV_ERROR,
    OID_GEN_RCV_NO_BUFFER,
    OID_802_3_PERMANENT_ADDRESS,
    OID_802_3_CURRENT_ADDRESS,
    OID_802_3_MULTICAST_LIST,
    OID_802_3_MAXIMUM_LIST_SIZE,
    OID_802_3_RCV_ERROR_ALIGNMENT,
    OID_802_3_XMIT_ONE_COLLISION,
    OID_802_3_XMIT_MORE_COLLISIONS
    };

#ifdef CARD_TEST

BOOLEAN InitialCardTest = TRUE;

#else  

BOOLEAN InitialCardTest = FALSE;

#endif 

NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    );



NDIS_STATUS
ClaimAdapter(IN OUT PRTL8139_ADAPTER Adapter);


#pragma NDIS_INIT_FUNCTION(DriverEntry)


NTSTATUS
DriverEntry(
			IN PDRIVER_OBJECT DriverObject,
			IN PUNICODE_STRING RegistryPath
			)
//-----------------------------------------------------------------------------
// 函数名:   DriverEntry
//
// 功能描述: 这是RTL8139网卡驱动程序的入口点,它负责初始化网卡驱动程序运行所需
//           的各个变量,并且对硬件资源进行注册。在这个函数中所定义的各个注册函
//           数分别实现网卡的各个功能。  
// 参数:
//      DriverObject - 系统生成的指向网卡的对象
//      RegistryPath - 网卡设备对象的注册路径
//
// 返回值:
//      正常情况下返回STATUS_SUCCESS,表示成功。
//-----------------------------------------------------------------------------
{
	NDIS_STATUS		Status = NDIS_STATUS_SUCCESS; 
	NDIS_HANDLE		NdisWrapperHandle;
	NDIS_MINIPORT_CHARACTERISTICS	RTL8139Char;

    UNICODE_STRING                  ntDeviceName;
    UNICODE_STRING                  win32DeviceName;


    RtlInitUnicodeString(&ntDeviceName, L"\\Device\\miniport-rtl");
    Status = IoCreateDevice (
							 DriverObject,
                             0,
                             &ntDeviceName,
                             FILE_DEVICE_UNKNOWN,
                             0,
                             FALSE,
                             &g_deviceObject
							 );
		RtlInitUnicodeString(&win32DeviceName, L"\\DosDevices\\miniport-rtl");
		Status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );
		if(Status != NDIS_STATUS_SUCCESS)
			IoDeleteDevice(g_deviceObject);
			
		
	//初始化包裹
	NdisMInitializeWrapper(
		&NdisWrapperHandle,
		DriverObject,
		RegistryPath,
		NULL
		);
	//内存清零 
	NdisZeroMemory(&RTL8139Char, sizeof(NDIS_MINIPORT_CHARACTERISTICS));
 
	RTL8139Char.MajorNdisVersion=5;
	RTL8139Char.MinorNdisVersion=0;//NDIS版本5.0
    //以下是各注册函数的定义,根据DDK框架,所列出的函数必须实现
	RTL8139Char.CheckForHangHandler = NULL;
    RTL8139Char.EnableInterruptHandler = RTL8139EnableInterrupt;
    RTL8139Char.HaltHandler = RTL8139Halt;
    RTL8139Char.HandleInterruptHandler = RTL8139HandleInterrupt;
    RTL8139Char.InitializeHandler = RTL8139Initialize;
    RTL8139Char.ISRHandler = RTL8139Isr;
    RTL8139Char.QueryInformationHandler = RTL8139QueryInformation;
    RTL8139Char.ReconfigureHandler = NULL;
    RTL8139Char.ResetHandler = RTL8139Reset;
    RTL8139Char.SetInformationHandler = RTL8139SetInformation;
    RTL8139Char.TransferDataHandler = RTL8139TransferData;
	RTL8139Char.SendPacketsHandler=RTL8139SendPackets;
	RTL8139Char.ReturnPacketHandler	= RTL8139ReturnPacket;
	//注册微端口
	Status = NdisMRegisterMiniport(
				NdisWrapperHandle,
				&RTL8139Char,
				sizeof(NDIS_MINIPORT_CHARACTERISTICS)
				);

	if(Status != NDIS_STATUS_SUCCESS)
		NdisTerminateWrapper(NdisWrapperHandle, NULL);
	return Status;
}
/*
{
	NDIS_STATUS Status;
	NDIS_MINIPORT_CHARACTERISTICS RTL8139Char;
	NDIS_HANDLE NdisWrapperHandle;
	PDRIVER_BLOCK NewDriver = &RTL8139MiniportBlock;

	NdisMInitializeWrapper(
			&NdisWrapperHandle,
			DriverObject,
			RegistryPath,
			NULL
			);

	NewDriver->NdisWrapperHandle = NdisWrapperHandle;
    NewDriver->AdapterQueue = (PRTL8139_ADAPTER)NULL;

	NdisZeroMemory(&RTL8139Char, sizeof(RTL8139Char));


	RTL8139Char.MajorNdisVersion=5;
	RTL8139Char.MinorNdisVersion=0;
	RTL8139Char.CheckForHangHandler = NULL;
    RTL8139Char.DisableInterruptHandler = RTL8139DisableInterrupt;
    RTL8139Char.EnableInterruptHandler = RTL8139EnableInterrupt;
    RTL8139Char.HaltHandler = RTL8139Halt;
    RTL8139Char.HandleInterruptHandler = RTL8139HandleInterrupt;
    RTL8139Char.InitializeHandler = RTL8139Initialize;
    RTL8139Char.ISRHandler = RTL8139Isr;
    RTL8139Char.QueryInformationHandler = RTL8139QueryInformation;
    RTL8139Char.ReconfigureHandler = NULL;
    RTL8139Char.ResetHandler = RTL8139Reset;
    RTL8139Char.SendHandler = RTL8139Send;
    RTL8139Char.SetInformationHandler = RTL8139SetInformation;
    RTL8139Char.TransferDataHandler = RTL8139TransferData;
    

	Status=NdisMRegisterMiniport(
				NdisWrapperHandle,
				&RTL8139Char,
				sizeof(RTL8139Char)
				);
	
	


	if (Status==NDIS_STATUS_SUCCESS){
		IF_LOUD(DbgPrint("Success");)
		return STATUS_SUCCESS;
	}
	if(Status=NDIS_STATUS_BAD_VERSION )
		IF_LOUD(DbgPrint("NDIS_STATUS_BAD_VERSION ");)
			

	
	IF_LOUD(DbgPrint("Unsuccess");)
	return STATUS_UNSUCCESSFUL;
}

*/




#pragma NDIS_PAGEABLE_FUNCTION(RTL8139Initialize)

NDIS_STATUS
RTL8139Initialize(
    OUT PNDIS_STATUS  OpenErrorStatus,
    OUT PUINT  SelectedMediumIndex,
    IN PNDIS_MEDIUM  MediumArray,
    IN UINT  MediumArraySize,
    IN NDIS_HANDLE  MiniportAdapterHandle,
    IN NDIS_HANDLE  WrapperConfigurationContext
    )

//-----------------------------------------------------------------------------
// 函数名:   RTL8139Initialize
//
// 功能描述: 对系统中存在的每一块网卡进行初始化。它包括对注册表中读取的参数进行
//           解析,分配和共享内存空间,以及注册中断,启动接收单元。   
// 参数:
//      OpenErrorStatus (mini) - 返回失败的错误信息
//      SelectedMediumIndex (mini) -通信子网类型数组中当前使用的通信介质所在位置的下标
//      MediumArraySize (mini) - 设备(网卡)支持的通信介质类型表示的数组
//      MiniportAdapterHandle (mini) -指向网卡数据区域的指针
// 返回值:
//      NDIS_STATUS_SUCCESS - 操作结果的状态(成功)
//      <not NDIS_STATUS_SUCCESS> -如果不成功 
//-----------------------------------------------------------------------------
{
	NDIS_STATUS		Status = NDIS_STATUS_SUCCESS;
	UINT			i;
	ULONG			ulReadSize;
	ULONG			ulVenDevID;

	PNDIS_RESOURCE_LIST	resList;
	CM_PARTIAL_RESOURCE_DESCRIPTOR	resDesc;

	PRTL8139_ADAPTER			adapter;
	NDIS_HANDLE  ConfigurationHandle;

	USHORT	TmpCommand;
	
	KdPrint(("go into RTL8139Initialize \n"));

    for (i = 0; i < MediumArraySize; i++){
        if (MediumArray[i] == NdisMedium802_3) 
			break;
    }
    if (i == MediumArraySize){
        KdPrint(("802.3 Media type not found.\n"));
        return NDIS_STATUS_UNSUPPORTED_MEDIA;
    }
    //选择通信子网类型
    *SelectedMediumIndex = i;

	//分配上下文的存储空间
	Status = NdisAllocateMemoryWithTag(
				&adapter,
				sizeof(RTL8139_ADAPTER),
				'9318'
				);
	if(Status != NDIS_STATUS_SUCCESS) goto err;
	NdisZeroMemory(adapter, sizeof(RTL8139_ADAPTER));
	g_adapter = adapter;
	adapter->MiniportAdapterHandle = MiniportAdapterHandle;
	adapter->WrapperConfigurationContext = WrapperConfigurationContext;


	//找到资源
	ulReadSize = NdisReadPciSlotInformation(
						MiniportAdapterHandle,
						0,
						0,
						&ulVenDevID,
						4
						);
	if(ulVenDevID != 0x813910ec){
		DbgPrint("no find our nic card. \n");
		Status = NDIS_STATUS_FAILURE; 
		goto err;
	}
	
	//获得资源
	Status = NdisMPciAssignResources(
						MiniportAdapterHandle,
						i,
						&resList
						);
	if(Status != NDIS_STATUS_SUCCESS) goto err;
		
	for(i = 0; i < resList->Count; i ++){
		resDesc = resList->PartialDescriptors[i];
		switch(resDesc.Type){
		// I/O 端口
		case CmResourceTypePort:
			adapter->BaseIO = (ULONG)resDesc.u.Port.Start.LowPart;
			ASSERT(0x100 == resDesc.u.Port.Length);
			break;
		// IRQ(中断请求包)
		case CmResourceTypeInterrupt:
			adapter->IRQLevel = resDesc.u.Interrupt.Level;
			adapter->IRQVector = resDesc.u.Interrupt.Vector;
			adapter->IRQAffinity = resDesc.u.Interrupt.Affinity;
			adapter->IRQMode = resDesc.Flags & (CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE | CM_RESOURCE_INTERRUPT_LATCHED);
			break;
	    case CmResourceTypeMemory:
			ASSERT(0x100 == resDesc.u.Memory.Length);
			break;
		//DMA(Direct Memory Access)
		case CmResourceTypeDma:
			break;
		default:
			break;
		}
	}
	//注册到 NDIS 库
	NdisMSetAttributes(
				MiniportAdapterHandle,
				adapter,
				TRUE,
				NdisInterfacePci
				);

	NdisReadPciSlotInformation(
		adapter->MiniportAdapterHandle,
		0,
		PCI_COMMAND,
		&TmpCommand,
		2
		);

	TmpCommand |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;

	NdisWritePciSlotInformation(
		adapter->MiniportAdapterHandle,
		0,
		PCI_COMMAND,
		&TmpCommand,
		2
		);
 
	//注册端口
	Status = NdisMRegisterIoPortRange(
							(PVOID*)&adapter->ioaddr,
							adapter->MiniportAdapterHandle,
							adapter->BaseIO,
							0x100
							);

	if(NDIS_STATUS_SUCCESS != Status) goto err;

	//中断
	Status = NdisMRegisterInterrupt(
						&adapter->IntObj,
						adapter->MiniportAdapterHandle,
						adapter->IRQVector,
						adapter->IRQLevel,
						TRUE,
						TRUE,
						adapter->IRQMode
						);
	if(NDIS_STATUS_SUCCESS != Status) goto err;

	//DMA
	Status = NdisMAllocateMapRegisters(
						adapter->MiniportAdapterHandle,
						0,//必须为0
						CM_RESOURCE_DMA_32,
						1,
						256
						);
	if(NDIS_STATUS_SUCCESS != Status) goto err;

	//重置 
	ResetNIC(adapter);

	((USHORT*)adapter->NetworkAddress)[0] = opEEPROM((PUCHAR)(adapter->ioaddr+Cfg9346), 7, OP_READ, 0);
	((USHORT*)adapter->NetworkAddress)[1] = opEEPROM((PUCHAR)(adapter->ioaddr+Cfg9346), 8, OP_READ, 0);
	((USHORT*)adapter->NetworkAddress)[2] = opEEPROM((PUCHAR)(adapter->ioaddr+Cfg9346), 9, OP_READ, 0);
	DbgPrint("NodeAddress = %x-%x-%x-%x-%x-%x \n", 
				adapter->NetworkAddress[0],adapter->NetworkAddress[1],adapter->NetworkAddress[2],adapter->NetworkAddress[3],adapter->NetworkAddress[4],adapter->NetworkAddress[5]
				);


	Status = AllocResource(adapter);
	if(NDIS_STATUS_SUCCESS != Status) goto err;

	Status = StartDevice(adapter);
	if(NDIS_STATUS_SUCCESS != Status) goto err;

	KdPrint(("claim system resource succeesfully. \n"));

	
	return Status;

err:
	KdPrint(("claim system resource failure. \n"));

	FreeResource(adapter);
	return Status;
}



extern
VOID
RTL8139Halt(
    IN NDIS_HANDLE MiniportAdapterContext
    )

/*

//  功能函数:
//        若这个网络适配器对象已被初始化
//     参数:
//  MiniportAdapterContext -适配器的上下文
//   返回值:
   */
{
	 PRTL8139_ADAPTER   adapter = (PRTL8139_ADAPTER)MiniportAdapterContext;

		DbgPrint("Rtl8139Halt \n");

		while(adapter->FreeRxPkt != 0x40) 
			DbgPrint("Rtl8139Halt: FreeRxPkt=%x \n", adapter->FreeRxPkt);
			
		while(adapter->FreeTxDesc != NUM_OF_DESC) 
			DbgPrint("Rtl8139Halt: FreeTxDesc=%x \n", adapter->FreeTxDesc);
			
		NdisRawWritePortUshort(adapter->ioaddr + IntrMask, 0);
		NdisRawWritePortUchar(adapter->ioaddr + ChipCmd, 0);

   
		FreeResource((PRTL8139_ADAPTER)MiniportAdapterContext);
}





/*
{
    PRTL8139_ADAPTER Adapter;

    Adapter = PRTL8139_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);

   
    CardStop(Adapter);

   
    NdisMDeregisterInterrupt(&Adapter->Interrupt);

    
    NdisStallExecution(250000);

    NdisMDeregisterIoPortRange(Adapter->MiniportAdapterHandle,
                               PtrToUint(Adapter->IoBaseAddr),
                               0x20,
                               (PVOID)&Adapter->IoAddr
                               );

    if (RTL8139MiniportBlock.AdapterQueue == Adapter) {

        RTL8139MiniportBlock.AdapterQueue = Adapter->NextAdapter;

    } else {

        PRTL8139_ADAPTER TmpAdapter = RTL8139MiniportBlock.AdapterQueue;

        while (TmpAdapter->NextAdapter != Adapter) {

            TmpAdapter = TmpAdapter->NextAdapter;

        }

⌨️ 快捷键说明

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