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

📄 driver.c

📁 rtl8139网卡在Windows2000/xp下的驱动程序源代码,无线网卡驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
#include "driver.h"

//////////////////////////////////////////////////////////////////////////////////
//DriverEntry由系统调用来装载驱动程序。DriverEntry产生一个微端口驱动程序
//和NDIS库的连接,并且向NDIS注册微端口的版本和入口指针
NTSTATUS DriverEntry( IN PDRIVER_OBJECT  DriverObject,
                      IN PUNICODE_STRING  RegistryPath )
{
	NDIS_STATUS		Status = NDIS_STATUS_SUCCESS; 
	NDIS_HANDLE	NdisWrapperHandle;
    NDIS_MINIPORT_CHARACTERISTICS	R8139Char;
//----------------------------------------------------------------------------
    RtlInitUnicodeString(&ntDeviceName, L"\\Device\\miniport-rtl");
	RtlInitUnicodeString(&win32SymbolicLinkName, L"\\DosDevices\\miniport-rtl");
    Status = IoCreateDevice ( DriverObject,
                             0,
                             &ntDeviceName,  //内核设备名 向内核标识设备
                             FILE_DEVICE_UNKNOWN,
                             0,
                             FALSE, //不排斥,非独占的,一次可有多个线程同时访问该设备
                             &g_deviceObject);   
	if(Status == NDIS_STATUS_SUCCESS)
	{	//创建一个符号链接来使得内核设备名对WIN32可用
		Status = IoCreateSymbolicLink( &win32SymbolicLinkName, //win32符号链接名
			                           &ntDeviceName );  //内核设备名
		if(Status != NDIS_STATUS_SUCCESS)
			IoDeleteDevice(g_deviceObject);
	}
//------------------------------------------------------------------------------

//为miniport驱动程序初始化NDIS库数据结构, 产生 微端口驱动程序与NDIS库的一个连接
//将驱动程序对象的地址DriverObject和指向驱动程序具体信息的有关注册表路径RegistryPath作为参数
//返回代表这个微端口NIC驱动程序结构的句柄NdisWrapperHandle, 若失败,则为NULL
	NdisMInitializeWrapper(&NdisWrapperHandle, //OUT PNDIS_HANDLE  NdisWrapperHandle,
		                       DriverObject,   //IN PVOID  SystemSpecific1
							   RegistryPath,   //IN PVOID  SystemSpecific2
							       NULL);      //IN PVOID  SystemSpecific3
    if (NdisWrapperHandle == NULL)
        return NDIS_STATUS_FAILURE;
	
	NdisZeroMemory(&R8139Char, sizeof(NDIS_MINIPORT_CHARACTERISTICS));
	R8139Char.MajorNdisVersion	= 5;
	R8139Char.MinorNdisVersion	= 0;
	R8139Char.CheckForHangHandler= RCheck;        //MiniportCheckForHang
	R8139Char.HaltHandler		= RHalt;          //MiniportHalt
	R8139Char.HandleInterruptHandler= RIsrDpc;	  //MiniportHandleInterrupt 
	R8139Char.InitializeHandler = RInit;          //MiniportInitialize
	R8139Char.ISRHandler			= RIsr;       //MiniportISR              
	R8139Char.QueryInformationHandler	= RQuery; //MiniportQueryInformation
	R8139Char.ResetHandler		= RReset;         //MiniportReset             
	R8139Char.SetInformationHandler	= RSet;       //MiniportSetInformation   
	R8139Char.ReturnPacketHandler	= RReturnPkt; //MiniportReturnPacket      
	R8139Char.SendPacketsHandler	= RSendPkts;  //MiniportSendPackets       

//将自己(微端口驱动程序的MiniportXxx入口点)注册到NDIS(NdisWrapperHandle)
	Status = NdisMRegisterMiniport(NdisWrapperHandle, //IN NDIS_HANDLE  NdisWrapperHandle
				                     &R8139Char,  //IN PNDIS_MINIPORT_CHARACTERISTICS  MiniportCharacteristics,
				sizeof(NDIS_MINIPORT_CHARACTERISTICS));  //IN UINT  CharacteristicsLength
	if(Status != NDIS_STATUS_SUCCESS)
		NdisTerminateWrapper(NdisWrapperHandle, NULL); //释放微端口驱动程序调用NdisMInitializeWrapper时分配的系统资源

    DriverObject->MajorFunction[IRP_MJ_CREATE] = ROpen;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]  = RClose;
	DriverObject->MajorFunction[IRP_MJ_READ]   = RRead;
	DriverObject->MajorFunction[IRP_MJ_WRITE]  = RWrite;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = RIoControl;
	DriverObject->MajorFunction[IRP_MJ_CLEANUP]  = RCleanup;
	DriverObject->DriverUnload = RUnload;

	return Status;
}

//////////////////////////////////////////////////////////////////////
//NDIS每两秒调用一次MiniportCheckForHang函数来检查NIC的运行状态
//如果它检测到NIC工作不正常,那么MiniportCheckForHang返回TRUE;否则,它返回FALSE
//如果返回TRUE,NDIS将调用MiniportReset函数
BOOLEAN  RCheck( IN NDIS_HANDLE  MiniportAdapterContext)
{
	return FALSE;
}

//////////////////////////////////////////////////////////////////////
//终止一个微端口驱动程序, 释放由微端口MiniportInitialize所声明的系统资源
VOID RHalt( IN NDIS_HANDLE  MiniportAdapterContext )
{
    PADAPTER   adapter = (PADAPTER)MiniportAdapterContext;
	NdisRawWritePortUshort(adapter->ioaddr + IntrMask, 0); //禁止所有中断
	NdisRawWritePortUchar(adapter->ioaddr + ChipCmd, 0);   //接收、传输禁止
	FreeRes((PADAPTER)MiniportAdapterContext);
}


//////////////////////////////////////////////////////////////////////////////
//#pragma LOCK_CODE
VOID RIsr(OUT PBOOLEAN  InterruptRecognized, 
    OUT PBOOLEAN  QueueMiniportHandleInterrupt,
    IN NDIS_HANDLE  MiniportAdapterContext )
{
	PADAPTER	adapter = (PADAPTER)MiniportAdapterContext;
	USHORT		currentISR;

	NdisRawReadPortUshort(adapter->ioaddr + IntrStatus, &currentISR);
	if(currentISR & R39_INTERRUPT_MASK)
	{
		NdisRawWritePortUshort(adapter->ioaddr + IntrMask, 0);  //禁止所有中断
		adapter->curISR = currentISR & R39_INTERRUPT_MASK;
		*InterruptRecognized = TRUE;//若检测到来自NIC的中断则设该变量为TRUE
		*QueueMiniportHandleInterrupt = TRUE;
//如果应该调用MiniportHandleInterrupt函数来处理中断则设QueueMiniportHandleInterrupt为TRUE
	}else
	{
		*InterruptRecognized = FALSE;
		*QueueMiniportHandleInterrupt = FALSE;
	}
}

//////////////////////////////////////////////////////////////////////
//#pragma LOCK_CODE  处理中断
VOID RIsrDpc(  IN NDIS_HANDLE  MiniportAdapterContext  )
{
	PADAPTER	adapter = (PADAPTER)MiniportAdapterContext;
	USHORT		write_ptr;
    if((adapter->curISR & TxOK)||(adapter->curISR & TxErr)) //如果包传送成功结束或由于过量冲突而丢弃
		TxInt(adapter);
	if(adapter->curISR & RxOK)  // 表明包接收成功结束
		RxInt(adapter);
    if( adapter->curISR & (RxErr|RxOverflow|RxFIFOOver))
	{  // 接收包有CRC错误或帧对齐错误 | 接收环状缓冲区资源耗尽 | 接收FIFO溢出
		NdisRawReadPortUshort(adapter->ioaddr + RxBufAddr, &write_ptr);
//当前的缓冲区地址指针,初值为0x0000,它反映了接收缓冲区中接收到的字节总数
		adapter->read_ptr = write_ptr % RING_BUF_SIZE;//求余 得到环状缓冲区数据拷贝的末地址
		NdisRawWritePortUshort(adapter->ioaddr + RxBufPtr, adapter->read_ptr - 16);
		NdisRawWritePortUshort(adapter->ioaddr + IntrStatus, RxOK);  //写入ISR没效果
	}
	NdisRawWritePortUshort(adapter->ioaddr + IntrMask, R39_INTERRUPT_MASK); //使能大多数中断
}

////////////////////////////////////////////////////////////////////////////
//当在微端口DriverEntry函数中调用NdisMRegisterMiniport函数返回时,
//NDIS立即为每个微端口管理的NIC,调用微端口的MiniportInitialize函数
NDIS_STATUS RInit(
    OUT PNDIS_STATUS  OpenErrorStatus,
    OUT PUINT  SelectedMediumIndex,
    IN PNDIS_MEDIUM  MediumArray,
    IN UINT        MediumArraySize,
    IN NDIS_HANDLE  MiniportAdapterHandle,
    IN NDIS_HANDLE  WrapperConfigurationContext)
{
	UINT			i;
	NDIS_STATUS		Status = NDIS_STATUS_SUCCESS;
    PADAPTER		adapter;
	ULONG           ulReadSize ;
	ULONG			ulVenDevID;
	PNDIS_RESOURCE_LIST	resList;
	CM_PARTIAL_RESOURCE_DESCRIPTOR	resDesc;
	USHORT	      TmpCommand;
	
	KdPrint(("go into RInit \n"));
	
    for (i = 0; i < MediumArraySize; i++)  //  媒体类型定义
	{   //  MediumArray 操作系统支持的媒体类型
        if (MediumArray[i] == NdisMedium802_3) 
			break;  //跳出本层循环 
    }
    if (i == MediumArraySize) // 表示没发现MediumArray[i] == NdisMedium802_3
	{
        KdPrint(("802.3 Media type not found.\n"));
        return NDIS_STATUS_UNSUPPORTED_MEDIA;
    }
    *SelectedMediumIndex = i; // return the selected medium type
//------------------------------------------------------------------------------	
//分配驻留(不分页)的系统空间内存,允许调用者提供一个可用来跟踪驱动程序内存分配的标记
	Status = NdisAllocateMemoryWithTag(
		        &adapter, //OUT PVOID  *VirtualAddress  存储该函数返回所分配的内存虚拟基地址
				sizeof(ADAPTER),  //IN UINT  Length
				'9318');   //IN ULONG  Tag 'dehw' 可达到4字节,反顺序
	if(Status != NDIS_STATUS_SUCCESS) 
		goto err;
	NdisZeroMemory(adapter, sizeof(ADAPTER));
	g_adapter = adapter;
	adapter->MiniportAdapterHandle = MiniportAdapterHandle;
//------------------------------------------------------------------------------
//告知NDIS库在初始化过程中的有关调用者的NIC的重要属性
	NdisMSetAttributes(	MiniportAdapterHandle,//IN NDIS_HANDLE MiniportAdapterHandle,
				       adapter,    //IN NDIS_HANDLE MiniportAdapterContext,
				         TRUE,     //IN BOOLEAN  BusMaster,
				NdisInterfacePci);  //IN NDIS_INTERFACE_TYPE  AdapterType
//------------------------------------------------------------------------------
//从PCI设备的配置空间获得PCI总线的配置信息
	ulReadSize = NdisReadPciSlotInformation(
						MiniportAdapterHandle, //IN NDIS_HANDLE  NdisAdapterHandle,
						0,  //IN ULONG  SlotNumber,保留值,NDIS忽略该参数
						0,  //IN ULONG  Offset指定PCI配置空间内的字节偏移量,从该处开始来传输配置信息
						&ulVenDevID, //IN PVOID  Buffer
						4); //IN ULONG  Length
	if(ulVenDevID != 0x813910ec)
	{
		DbgPrint("no find our nic card. \n");
		Status = NDIS_STATUS_FAILURE; 
		goto err;
	}
// I/O空间访问使能  MEMORY空间访问使能  总线Master使能
	NdisReadPciSlotInformation(
		adapter->MiniportAdapterHandle,
		0,//IN ULONG  SlotNumber,保留值,NDIS忽略该参数
		PCI_COMMAND,  //0x04 指定PCI配置空间内的字节偏移量,从该处开始来传输配置信息
		&TmpCommand,
		2);//IN ULONG  Length
	TmpCommand |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
	NdisWritePciSlotInformation(
		adapter->MiniportAdapterHandle,
		0,
		PCI_COMMAND,
		&TmpCommand,
		2);
//------------------------------------------------------------------------------
//返回注册表中的PCI NIC的特定硬件资源,例如 IRQ ,I/O端口,存储器范围
//在 windows xp及以后版本,该函数由NdisMQueryAdapterResources代替
	Status = NdisMPciAssignResources(MiniportAdapterHandle, //IN NDIS_HANDLE  MiniportHandle
						0,  // IN ULONG  SlotNumber 保留值,NDIS忽略该参数
						&resList);  //OUT PNDIS_RESOURCE_LIST  *AssignedResources
	if(Status != NDIS_STATUS_SUCCESS) 
		goto err;
	for(i = 0; i < resList->Count; i ++)
	{
		resDesc = resList->PartialDescriptors[i];
		switch(resDesc.Type)
		{
		case CmResourceTypePort:  //I/O端口资源
			adapter->BaseIO = (ULONG)resDesc.u.Port.Start.LowPart; //端口总线特定的开始地址
			ASSERT(0x100 == resDesc.u.Port.Length);
			break;
		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:  //内存资源   8139不使用内存资源
//			break;
		default:
			break;
		}
	}
//------------------------------------------------------------------------------
//sets up driver access to device I/O ports with the NdisRawReadPortXxx and NdisRawWritePortXxx 
//functions and claims the range of I/O port addresses in the registry for that driver's NIC
//在adapter->ioaddr中返回映射的虚拟基地址,
//用于在NdisRawReadPortXxx 和 NdisRawWritePortXxx 函数中读写NIC的寄存器
	Status = NdisMRegisterIoPortRange(
							(PVOID*)&adapter->ioaddr,//OUT PVOID  *PortOffset 返回映射的虚拟基地址
							adapter->MiniportAdapterHandle,
							adapter->BaseIO, //IN UINT  InitialPort
							0x100);//IN UINT  NumberOfPorts
	if(NDIS_STATUS_SUCCESS != Status) 
		goto err;
	((USHORT*)adapter->NetworkAddress)[0] = readEEPROM((PUCHAR)(adapter->ioaddr+Cmd93C46), 7);
	((USHORT*)adapter->NetworkAddress)[1] = readEEPROM((PUCHAR)(adapter->ioaddr+Cmd93C46), 8);
	((USHORT*)adapter->NetworkAddress)[2] = readEEPROM((PUCHAR)(adapter->ioaddr+Cmd93C46), 9);
//------------------------------------------------------------------------------
	Status = AllocRes(adapter);
	if(NDIS_STATUS_SUCCESS != Status) 
		goto err;
//------------------------------------------------------------------------------
	Status = NdisMRegisterInterrupt(
						&adapter->IntObj, //OUT PNDIS_MINIPORT_INTERRUPT  Interrupt
						adapter->MiniportAdapterHandle,

⌨️ 快捷键说明

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