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

📄 driver.c

📁 RTL8139驱动源码
💻 C
📖 第 1 页 / 共 3 页
字号:
#define	NDIS_WDM 1

#define NDIS_MINIPORT_DRIVER
#define NDIS50_MINIPORT   1 

#include "ndis.h"  // AFTER preceding directives

#include "driver.h"
#include "8139.h"
 

PDEVICE_OBJECT      g_deviceObject;
PADAPTER			g_adapter;

NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT  DriverObject,
    IN PUNICODE_STRING  RegistryPath
    )
{
	NDIS_STATUS		Status = NDIS_STATUS_SUCCESS; 
	NDIS_HANDLE		NdisWrapperHandle;
	NDIS_MINIPORT_CHARACTERISTICS	R8139Char;

    UNICODE_STRING                  ntDeviceName;
    UNICODE_STRING                  win32DeviceName;


    RtlInitUnicodeString(&ntDeviceName, L"\\Device\\miniport-rtl");
    Status = IoCreateDevice (
							 DriverObject,
                             0,
                             &ntDeviceName,
                             FILE_DEVICE_UNKNOWN,
                             0,
                             FALSE,
                             &g_deviceObject
							 );

    
	if(Status != NDIS_STATUS_SUCCESS)
		DbgPrint("DriverEntry:IoCreateDevice failure. \n");
	else{
		RtlInitUnicodeString(&win32DeviceName, L"\\DosDevices\\miniport-rtl");
		Status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );
		if(Status != NDIS_STATUS_SUCCESS){
			IoDeleteDevice(g_deviceObject);
			DbgPrint("DriverEntry:IoCreateSymbolicLink failure. \n");
		}else
			DbgPrint("DriverEntry:IoCreateDevice success. \n");
	}

//	g_deviceObject->Flags |= DO_DIRECT_IO;

	//init wrapper
	NdisMInitializeWrapper(
		&NdisWrapperHandle,
		DriverObject,
		RegistryPath,
		NULL
		);
	//clear zero
	NdisZeroMemory(&R8139Char, sizeof(NDIS_MINIPORT_CHARACTERISTICS));
 
	R8139Char.MajorNdisVersion	= 5;
	R8139Char.MinorNdisVersion	= 0;
	R8139Char.InitializeHandler = RInit;
	R8139Char.HaltHandler		= RHalt;
	R8139Char.QueryInformationHandler	= RQuery;
	R8139Char.SetInformationHandler	= RSet;
	R8139Char.ResetHandler		= RReset;
	R8139Char.ReturnPacketHandler	= RReturnPkt;
	R8139Char.SendPacketsHandler	= RSendPkts;
	R8139Char.ISRHandler			= RIsr;
	R8139Char.HandleInterruptHandler= RIsrDpc;
	R8139Char.CheckForHangHandler= RCheck;
//	R8139Char.DisableInterruptHandler = RDisint;

	//register miniport
	Status = NdisMRegisterMiniport(
				NdisWrapperHandle,
				&R8139Char,
				sizeof(NDIS_MINIPORT_CHARACTERISTICS)
				);

	if(Status != NDIS_STATUS_SUCCESS)
		NdisTerminateWrapper(NdisWrapperHandle, NULL);


    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_CLEANUP]  = RCleanup;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = RIoControl;
	DriverObject->DriverUnload = RUnload;

	return Status;
}


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
    )
{
	NDIS_STATUS		Status = NDIS_STATUS_SUCCESS;
	UINT			i;
	ULONG			ulReadSize;
	ULONG			ulVenDevID;

	PNDIS_RESOURCE_LIST	resList;
	CM_PARTIAL_RESOURCE_DESCRIPTOR	resDesc;

	PADAPTER			adapter;
	NDIS_HANDLE  ConfigurationHandle;

	USHORT	TmpCommand;
	
	KdPrint(("go into RInit \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;
    }
    // Select ethernet
    *SelectedMediumIndex = i;

	//alloc adapter context mem
	Status = NdisAllocateMemoryWithTag(
				&adapter,
				sizeof(ADAPTER),
				'9318'
				);
	if(Status != NDIS_STATUS_SUCCESS) goto err;
	NdisZeroMemory(adapter, sizeof(ADAPTER));
	g_adapter = adapter;
	adapter->MiniportAdapterHandle = MiniportAdapterHandle;
	adapter->WrapperConfigurationContext = WrapperConfigurationContext;


	//find resourcs
	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;
			//share
			adapter->IRQMode = resDesc.Flags & (CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE | CM_RESOURCE_INTERRUPT_LATCHED);
			break;
		// MEMERY
		case CmResourceTypeMemory:
			ASSERT(0x100 == resDesc.u.Memory.Length);
			break;
		// DMA
		case CmResourceTypeDma:
			break;
		default:
			break;
		}
	}//for

	//regist to NDIS library
	NdisMSetAttributes(
				MiniportAdapterHandle,
				adapter,
				TRUE,//DMABusMaster,
				NdisInterfacePci
				);


	//enable dma
	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
		);
 
	//Registering Ports
	Status = NdisMRegisterIoPortRange(
							(PVOID*)&adapter->ioaddr,
							adapter->MiniportAdapterHandle,
							adapter->BaseIO,
							0x100
							);

	if(NDIS_STATUS_SUCCESS != Status) goto err;

	//interrupt
	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,//must 0
						CM_RESOURCE_DMA_32,
						1,
						256//dma transtrate max = 2k
						);
	if(NDIS_STATUS_SUCCESS != Status) goto err;

	//RESET 
	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 = AllocRes(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"));

	FreeRes(adapter);
	return Status;
}



//IRQL:DISPATCH_LEVEL
NDIS_STATUS 
RSet(
    IN NDIS_HANDLE  Context,
    IN NDIS_OID  Oid,
    IN PVOID  inbuf,
    IN ULONG  buf_size,
    OUT PULONG  BytesRead,
    OUT PULONG  BytesNeeded
    )
{
    NDIS_STATUS     Status = NDIS_STATUS_SUCCESS;
	UINT		i;
    PADAPTER   adapter = (PADAPTER)Context;


	switch(Oid){
	case OID_802_3_MULTICAST_LIST:
	//	DbgPrint("OID_802_3_MULTICAST_LIST. \n");
        if ( buf_size > 8)
            return (NDIS_STATUS_INVALID_LENGTH);
		else
			NdisMoveMemory(adapter->mc_filter, inbuf, buf_size);
		break;

    case OID_GEN_CURRENT_PACKET_FILTER:
	//	DbgPrint("OID_GEN_CURRENT_PACKET_FILTER. \n");
        // Verify the Length
        if (buf_size != 4)
            return (NDIS_STATUS_INVALID_LENGTH);
        adapter->PacketFilter = *(PULONG)inbuf;
        *BytesRead = buf_size;
        break;
    case OID_GEN_CURRENT_LOOKAHEAD:
        if (buf_size != 4)
            return (NDIS_STATUS_INVALID_LENGTH);
        *BytesRead = 4;
        break;
    default:
        Status = NDIS_STATUS_INVALID_OID;
        break;
	}

	return Status;
}



NDIS_STATUS 
RQuery(
    IN NDIS_HANDLE  Context,
    IN NDIS_OID  Oid,
    IN PVOID  inbuf,
    IN ULONG  buf_size,
    OUT PULONG  BytesWritten,
    OUT PULONG  BytesNeeded
    )
{
    NDIS_STATUS     Status = NDIS_STATUS_SUCCESS;
	UINT		i;
    PADAPTER   adapter = (PADAPTER)Context;


static NDIS_OID        OID_LIST[] =
    {
		//	Required OIDs
		OID_GEN_SUPPORTED_LIST,//					0x00010101
		OID_GEN_HARDWARE_STATUS,//					0x00010102
		OID_GEN_MEDIA_SUPPORTED,//					0x00010103
		OID_GEN_MEDIA_IN_USE,//						0x00010104
		OID_GEN_MAXIMUM_LOOKAHEAD,//				0x00010105
		OID_GEN_MAXIMUM_FRAME_SIZE,//				0x00010106
		OID_GEN_LINK_SPEED,//						0x00010107
		OID_GEN_TRANSMIT_BUFFER_SPACE,//			0x00010108
		OID_GEN_RECEIVE_BUFFER_SPACE,//				0x00010109
		OID_GEN_TRANSMIT_BLOCK_SIZE,//				0x0001010A
		OID_GEN_RECEIVE_BLOCK_SIZE,//				0x0001010B
		OID_GEN_VENDOR_ID,//						0x0001010C
		OID_GEN_VENDOR_DESCRIPTION,//				0x0001010D
		OID_GEN_CURRENT_PACKET_FILTER,//			0x0001010E
		OID_GEN_CURRENT_LOOKAHEAD,//				0x0001010F
		OID_GEN_DRIVER_VERSION,//					0x00010110
		OID_GEN_MAXIMUM_TOTAL_SIZE,//				0x00010111
		OID_GEN_PROTOCOL_OPTIONS,//					0x00010112
		OID_GEN_MAC_OPTIONS,//						0x00010113
		OID_GEN_MEDIA_CONNECT_STATUS,//				0x00010114
		OID_GEN_MAXIMUM_SEND_PACKETS,//				0x00010115
		OID_GEN_VENDOR_DRIVER_VERSION,//			0x00010116
		OID_GEN_SUPPORTED_GUIDS,//					0x00010117
		OID_GEN_NETWORK_LAYER_ADDRESSES,//			0x00010118	// Set only
		OID_GEN_TRANSPORT_HEADER_OFFSET,//			0x00010119  // Set only

		// 802.3 Objects (Ethernet)
		OID_802_3_PERMANENT_ADDRESS,//				0x01010101
		OID_802_3_CURRENT_ADDRESS,//				0x01010102
		OID_802_3_MULTICAST_LIST,//					0x01010103
		OID_802_3_MAXIMUM_LIST_SIZE,//				0x01010104
		OID_802_3_MAC_OPTIONS,//					0x01010105

		NDIS_802_3_MAC_OPTION_PRIORITY,//			0x00000001

		OID_802_3_RCV_ERROR_ALIGNMENT,//			0x01020101
		OID_802_3_XMIT_ONE_COLLISION,//				0x01020102
		OID_802_3_XMIT_MORE_COLLISIONS,//			0x01020103

		OID_802_3_XMIT_DEFERRED,//					0x01020201
		OID_802_3_XMIT_MAX_COLLISIONS,//			0x01020202
		OID_802_3_RCV_OVERRUN,//					0x01020203
		OID_802_3_XMIT_UNDERRUN,//					0x01020204
		OID_802_3_XMIT_HEARTBEAT_FAILURE,//			0x01020205
		OID_802_3_XMIT_TIMES_CRS_LOST,//			0x01020206
		OID_802_3_XMIT_LATE_COLLISIONS,//			0x01020207

		// 用户定义
		USER_OID_REV_BYTE,//						0x02000000
		USER_OID_XMIT_BYTE	,//						0x02000001
		//	Required statistics
		OID_GEN_XMIT_OK,//							0x00020101
		OID_GEN_RCV_OK,//							0x00020102
		OID_GEN_XMIT_ERROR,//						0x00020103
		OID_GEN_RCV_ERROR,//						0x00020104
		OID_GEN_RCV_NO_BUFFER,//					0x00020105

    };


	*BytesWritten = 4;

    switch (Oid){
	case USER_OID_REV_BYTE:
        *((PULONG)inbuf) =  adapter->rev_byte; 
		break;
	
	case USER_OID_XMIT_BYTE:
        *((PULONG)inbuf) =  adapter->xmit_byte; 
		break;

	case OID_GEN_SUPPORTED_LIST:
		if(buf_size < sizeof(OID_LIST)){
			*BytesNeeded = sizeof(OID_LIST);
			Status = NDIS_STATUS_INVALID_LENGTH;
		}else{
			NdisMoveMemory(inbuf, OID_LIST, sizeof(OID_LIST));
			*BytesWritten = sizeof(OID_LIST);
		}
        break;
	case OID_GEN_CURRENT_PACKET_FILTER:
		if(buf_size >= 4){
			*(PULONG)inbuf = adapter->PacketFilter;
			*BytesWritten = 4;
		}else
			*BytesNeeded = 4;
		break;
	case OID_GEN_MAC_OPTIONS:
        *((PULONG)inbuf) = (ULONG)(NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
            NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA  |
            NDIS_MAC_OPTION_NO_LOOPBACK
            );
        break;
    case OID_GEN_HARDWARE_STATUS:
		*((NDIS_HARDWARE_STATUS*)inbuf) = NdisHardwareStatusReady;
        break;
    case OID_GEN_MEDIA_SUPPORTED:
    case OID_GEN_MEDIA_IN_USE:
		*((NDIS_MEDIUM*)inbuf) = (NDIS_MEDIUM)(NdisMedium802_3);
        break;
    case OID_GEN_MAXIMUM_LOOKAHEAD:
    case OID_GEN_CURRENT_LOOKAHEAD:
    case OID_GEN_MAXIMUM_FRAME_SIZE:
        *((PULONG)inbuf) = MAX_ETHERNET_FRAME_SIZE - MAC_HEADER_SIZE;
        break;
    case OID_GEN_MAXIMUM_TOTAL_SIZE:
    case OID_GEN_TRANSMIT_BLOCK_SIZE:
    case OID_GEN_RECEIVE_BLOCK_SIZE:
        *((PULONG)inbuf) = (ULONG)MAX_ETHERNET_FRAME_SIZE;
        break;
    case OID_GEN_LINK_SPEED:
        *((PULONG)inbuf) =  1000000; //100m
        break;
    case OID_GEN_TRANSMIT_BUFFER_SPACE:
		DbgPrint("data=%x, len=%x\n", inbuf, buf_size);
        *((PULONG)inbuf) = (ULONG) MAX_ETHERNET_FRAME_SIZE * 4;
        break;
    case OID_GEN_RECEIVE_BUFFER_SPACE:
        *((PULONG)inbuf) = (ULONG)RING_BUF_SIZE;
        break;
    case OID_GEN_VENDOR_ID:
        *((PULONG)inbuf) = *(PULONG)adapter->NetworkAddress;
        break;
    case OID_GEN_VENDOR_DESCRIPTION:
        *((PULONG)inbuf) = (ULONG)'0900';
        break;
    case OID_GEN_DRIVER_VERSION:
        *((PULONG)inbuf) = (USHORT)0x0201;
        break;
    case OID_GEN_MAXIMUM_SEND_PACKETS:
        *((PULONG)inbuf) = (ULONG) NUM_OF_DESC;
        break;
    case OID_GEN_MEDIA_CONNECT_STATUS:
        *((PULONG)inbuf) = (ULONG)NdisMediaStateConnected;
        break;
		//
		// 802.3 Objects (Ethernet)
		//
	case OID_802_3_PERMANENT_ADDRESS://				0x01010101
        NdisMoveMemory(inbuf, adapter->NetworkAddress, 6);
		*BytesWritten = 6;
        break;
	case OID_802_3_CURRENT_ADDRESS://				0x01010102
        NdisMoveMemory(inbuf, adapter->NetworkAddress, 6);
		*BytesWritten = 6;
        break;
	case OID_802_3_MULTICAST_LIST://					0x01010103
        if (buf_size < 8)
            return (NDIS_STATUS_INVALID_LENGTH);
		else
			NdisMoveMemory(inbuf, adapter->mc_filter, buf_size);
        break;
	case OID_802_3_MAXIMUM_LIST_SIZE://				0x01010104
        *((PULONG)inbuf) = (ULONG)MULTICAST_FILTER_LIMIT;
        break;
	case OID_802_3_MAC_OPTIONS://					0x01010105
		Status = NDIS_STATUS_NOT_SUPPORTED;
        break;
	case NDIS_802_3_MAC_OPTION_PRIORITY://			0x00000001
		Status = NDIS_STATUS_NOT_SUPPORTED;
        break;

	case OID_802_3_RCV_ERROR_ALIGNMENT://			0x01020101
        *((PULONG)inbuf) = (ULONG)0;
        break;
	case OID_802_3_XMIT_ONE_COLLISION://				0x01020102
        *((PULONG)inbuf) = (ULONG)0;
        break;
	case OID_802_3_XMIT_MORE_COLLISIONS://			0x01020103
        *((PULONG)inbuf) = (ULONG)0;
        break;

⌨️ 快捷键说明

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