📄 rtl8139.c
字号:
/****************************************************************************
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 + -