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

📄 rtl8029.c

📁 自编的RTL8029驱动程序,用DS3.1开发
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
COPYRIGHT (C) 2004.8 Hunnad
Rtl8029 IS MODIFIED BASED AT  NE2000  IN THE DDK2000 SAMPLE                                          
THIS FILE IS OPEN SOURCE,ANYONE CAN MODIFY IT FOR FREE                 

****************************************************************************/

/****************************************************************************
Module Name:
    rtl8029.c

Environment:
    Kernel Mode - Or whatever is the equivalent on WinNT

*****************************************************************************/
#include "precomp.h"


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

//
// Debugging definitions
//
#if DBG

//
// Default debug mode
//
//ULONG RTL8029DebugFlag =RTL8029_DEBUG_LOG;
ULONG RTL8029DebugFlag =0x11111111;

//
// Debug tracing defintions
//
#define RTL8029_LOG_SIZE 256
UCHAR RTL8029LogBuffer[RTL8029_LOG_SIZE]={0};
UINT RTL8029LogLoc = 0;

extern
VOID
RTL8029Log(UCHAR c) {

    RTL8029LogBuffer[RTL8029LogLoc++] = c;

	RTL8029LogBuffer[(RTL8029LogLoc + 4) % RTL8029_LOG_SIZE] = '\0';

	if (RTL8029LogLoc >= RTL8029_LOG_SIZE)
		RTL8029LogLoc = 0;
}

#endif



//
// This constant is used for places where NdisAllocateMemory
// needs to be called and the HighestAcceptableAddress does
// not matter.
//
NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
    NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);

//
// The global Miniport driver block.
//

DRIVER_BLOCK RTL8029MiniportBlock={0};

//
// List of supported OID for this driver.
//
STATIC UINT RTL8029SupportedOids[] = {
    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
    };

//
// Determines whether failing the initial card test will prevent
// the adapter from being registered.
//
#ifdef CARD_TEST

BOOLEAN InitialCardTest = TRUE;

#else  // CARD_TEST

BOOLEAN InitialCardTest = FALSE;

#endif // CARD_TEST

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



NDIS_STATUS
ClaimAdapter(IN OUT PRTL8029_ADAPTER Adapter);


#pragma NDIS_INIT_FUNCTION(DriverEntry)


NTSTATUS
DriverEntry(
			IN PDRIVER_OBJECT DriverObject,
			IN PUNICODE_STRING RegistryPath
			)
//-----------------------------------------------------------------------------
// Procedure:   DriverEntry
//
// Description: This is the primary initialization routine for the rtl8029
//              driver. It is simply responsible for the intializing the
//              wrapper and registering the adapter driver.  The routine gets
//              called once per driver, but rtl8029Initialize(miniport) 
//              will get called multiple times if there are
//              multiple adapters.
//
// Arguments:
//      DriverObject - Pointer to driver object created by the system.
//      RegistryPath - The registry path of this driver
//
// Returns:
//  The status of the operation, normally this will be NDIS_STATUS_SUCCESS
//-----------------------------------------------------------------------------

{
	NDIS_STATUS Status;
	NDIS_MINIPORT_CHARACTERISTICS RTL8029Char;
	NDIS_HANDLE NdisWrapperHandle;
	PDRIVER_BLOCK NewDriver = &RTL8029MiniportBlock;

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

	NewDriver->NdisWrapperHandle = NdisWrapperHandle;
    NewDriver->AdapterQueue = (PRTL8029_ADAPTER)NULL;
// Now we must initialize the wrapper, and then register the Miniport
	NdisZeroMemory(&RTL8029Char, sizeof(RTL8029Char));

// Initialize the Miniport characteristics for the call to
// NdisMRegisterMiniport.
	RTL8029Char.MajorNdisVersion=RTL8029_NDIS_MAJOR_VERSION;
	RTL8029Char.MinorNdisVersion=RTL8029_NDIS_MINOR_VERSION;
	RTL8029Char.CheckForHangHandler = NULL;
    RTL8029Char.DisableInterruptHandler = RTL8029DisableInterrupt;
    RTL8029Char.EnableInterruptHandler = RTL8029EnableInterrupt;
    RTL8029Char.HaltHandler = RTL8029Halt;
    RTL8029Char.HandleInterruptHandler = RTL8029HandleInterrupt;
    RTL8029Char.InitializeHandler = RTL8029Initialize;
    RTL8029Char.ISRHandler = RTL8029Isr;
    RTL8029Char.QueryInformationHandler = RTL8029QueryInformation;
    RTL8029Char.ReconfigureHandler = NULL;
    RTL8029Char.ResetHandler = RTL8029Reset;
    RTL8029Char.SendHandler = RTL8029Send;
    RTL8029Char.SetInformationHandler = RTL8029SetInformation;
    RTL8029Char.TransferDataHandler = RTL8029TransferData;


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


	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(RTL8029Initialize)

NDIS_STATUS
RTL8029Initialize(
	OUT PNDIS_STATUS OpenErrorStatus,
    OUT PUINT SelectedMediumIndex,
    IN PNDIS_MEDIUM MediumArray,
    IN UINT MediumArraySize,
    IN NDIS_HANDLE MiniportAdapterHandle,
    IN NDIS_HANDLE ConfigurationHandle
	)
//-----------------------------------------------------------------------------
// Procedure:   RTL8029Initialize
//
// Description: This routine is called once per each supported adapter card in
//              the system.  This routine is responsible for initializing each
//              adapter.  This includes parsing all of the necessary parameters
//              from the registry, allocating and initializing shared memory
//              structures, configuring the 82557 chip, registering the
//              interrupt, and starting the receive unit.
//
// Arguments:
//      OpenErrorStatus (mini) - Returns more info about any failure
//      SelectedMediumIndex (mini) - Returns the index in MediumArray of the
//                                   medium that the miniport is using
//      MediumArraySize (mini) - An array of medium types that the driver
//                               supports
//      MiniportAdapterHandle (mini) - pointer to the adapter object data area.
//
//      WrapperConfigurationContext (both) - A value that we will pass to
//                                           NdisOpenConfiguration.
//
//
// Returns:
//      NDIS_STATUS_SUCCESS - If the adapter was initialized successfully.
//      <not NDIS_STATUS_SUCCESS> - If for some reason the adapter didn't
//                                  initialize
//-----------------------------------------------------------------------------

{
	NDIS_STATUS Status;
	PRTL8029_ADAPTER Adapter;
	PVOID OverrideNetAddress;
	UINT IPLength;
	NDIS_HANDLE ConfigHandle;
	ULONG i;
	NDIS_INTERFACE_TYPE IfType;

	for (i = 0; i < MediumArraySize; i++){
		if (MediumArray[i] == NdisMedium802_3){
		    break;
		}

    }

	 if (i == MediumArraySize){
		 return( NDIS_STATUS_UNSUPPORTED_MEDIA );
	 }
	*SelectedMediumIndex = i;



	Status=NdisAllocateMemory(
				(PVOID *)&Adapter,
				sizeof(RTL8029_ADAPTER),
				0,
				HighestAcceptableMax
                );

	if (Status != NDIS_STATUS_SUCCESS) {
		IF_LOUD(DbgPrint("NdisAllocateMemory Failed");)

        return Status;

    }
	NdisZeroMemory (Adapter, sizeof(RTL8029_ADAPTER));
	Adapter->MiniportAdapterHandle=MiniportAdapterHandle;
	NdisOpenConfiguration(
            &Status,
            &ConfigHandle,
            ConfigurationHandle
            );

    if (Status != NDIS_STATUS_SUCCESS) {

        NdisFreeMemory(Adapter, sizeof(RTL8029_ADAPTER), 0);

        return Status;

    }


	NdisReadNetworkAddress(&Status,
        &OverrideNetAddress,
        &IPLength,
        ConfigHandle);

	 if ((IPLength == ETH_LENGTH_OF_ADDRESS) && (Status == NDIS_STATUS_SUCCESS))
        NdisMoveMemory(Adapter->StationAddress,
        OverrideNetAddress,
        ETH_LENGTH_OF_ADDRESS);

    NdisCloseConfiguration(ConfigHandle);



	IfType = NdisInterfacePci;

	NdisMSetAttributesEx(
        Adapter->MiniportAdapterHandle,
        (NDIS_HANDLE) Adapter,
        0,
        (ULONG)
        NDIS_ATTRIBUTE_DESERIALIZE |
        NDIS_ATTRIBUTE_BUS_MASTER,
        IfType
        );
	

	 if (ClaimAdapter(Adapter) != NDIS_STATUS_SUCCESS)
    {
       
        return NDIS_STATUS_FAILURE;
    }
	   if (RTL8029RegisterAdapter(Adapter,
          ConfigurationHandle,
         0,
          0
          ) != NDIS_STATUS_SUCCESS) {

        //
        // RTL8029RegisterAdapter failed.
        //
        NdisFreeMemory(Adapter, sizeof(RTL8029_ADAPTER), 0);

        return NDIS_STATUS_FAILURE;

    }


    IF_LOUD( DbgPrint( "RTL8029RegisterAdapter succeeded\n" );)

    return NDIS_STATUS_SUCCESS;

}






NDIS_STATUS
ClaimAdapter(IN OUT PRTL8029_ADAPTER Adapter)
{

	USHORT              VendorID = RTL8029_VENDOR_ID;
    USHORT              DeviceID = RTL8029_DEVICE_ID;
	USHORT				Slot=0x00;
	ULONG				Device_Vendor_Id;
	UINT				i;
	UINT				found=0;
	PNDIS_RESOURCE_LIST  AssignedResources;
	PCI_CARDS_FOUND_STRUC PciCardsFound;
	USHORT				PciCommandWord;
	NDIS_STATUS			Status;


	Adapter->BusType=NdisInterfacePci;
	Adapter->SlotNum=Slot;

	NdisReadPciSlotInformation(
        Adapter->MiniportAdapterHandle,
        Slot,
        PCI_VENDOR_ID_REGISTER,
        (PVOID) &Device_Vendor_Id,
        0x4);

    if ((((USHORT) Device_Vendor_Id) == VendorID) &&
        (((USHORT) (Device_Vendor_Id >> 16)) == DeviceID))
    {

		Status = NdisMPciAssignResources(
					Adapter->MiniportAdapterHandle,
					Slot,
				    &AssignedResources
				    );
		if (Status != NDIS_STATUS_SUCCESS)
        {
        	IF_LOUD(DbgPrint("NdisMPciAssignResources Failed");)
        	return 0;
        }

		for (i=0;i< AssignedResources->Count;i++ )
        {
            switch (AssignedResources->PartialDescriptors[i].Type)
            {
            case CmResourceTypePort:
                if (AssignedResources->PartialDescriptors[i].Flags & CM_RESOURCE_PORT_IO)
                {
				
                    PciCardsFound.PciSlotInfo[found].BaseIo =
                        (ULONG) ((AssignedResources)->PartialDescriptors[i].u.Port.Start.u.LowPart);
                }
                break;
            case CmResourceTypeInterrupt:
                PciCardsFound.PciSlotInfo[found].Level =
                    (UCHAR) ((AssignedResources)->PartialDescriptors[i].u.Interrupt.Level);
                PciCardsFound.PciSlotInfo[found].Vector  =
                    (UCHAR) ((AssignedResources)->PartialDescriptors[i].u.Interrupt.Vector);
                break;
            case CmResourceTypeMemory:
                if (((USHORT) (AssignedResources)->PartialDescriptors[i].u.Memory.Length) == 0x1000 )
                {
                    PciCardsFound.PciSlotInfo[found].MemPhysAddress =
                        (ULONG) ((AssignedResources)->PartialDescriptors[i].u.Memory.Start.u.LowPart);
                }
                break;
            }
        }

		 NdisReadPciSlotInformation(
				 Adapter->MiniportAdapterHandle,
				 Slot,
				 PCI_REV_ID_REGISTER,
				 &PciCardsFound.PciSlotInfo[found].ChipRevision,
				 0x1);

		 NdisReadPciSlotInformation(
            Adapter->MiniportAdapterHandle,
            Slot,
            PCI_SUBVENDOR_ID_REGISTER,
            &PciCardsFound.PciSlotInfo[found].SubVendor_DeviceID,
            0x4);

		PciCardsFound.PciSlotInfo[found].SlotNumber = (USHORT) Slot;

		if ((PciCardsFound.PciSlotInfo[found].MemPhysAddress == 0) ||
            (PciCardsFound.PciSlotInfo[found].MemPhysAddress == 0xfffffff0) ||
            (PciCardsFound.PciSlotInfo[found].BaseIo == 0) ||
            (PciCardsFound.PciSlotInfo[found].BaseIo == 0xfffffffc) ||
            (PciCardsFound.PciSlotInfo[found].Level== 0xff))
        {
        	IF_LOUD(DbgPrint("Resources Assign Failed");)
        }
		 else
        {
			 NdisReadPciSlotInformation(
				 Adapter->MiniportAdapterHandle,
				 Slot,
                 PCI_COMMAND_REGISTER,
                 &PciCommandWord,
                0x2);


            if ((PciCommandWord & CMD_MEM_WRT_INVALIDATE) && (Adapter->MWIEnable))
            {
              
                Adapter->MWIEnable = TRUE;
            }
            else
            {
                Adapter->MWIEnable = FALSE;
            }

            if (!(PciCommandWord & CMD_BUS_MASTER))
            {
                PciCommandWord |= CMD_BUS_MASTER;

                NdisWritePciSlotInformation(
                    Adapter->MiniportAdapterHandle,
                    Slot,
                    PCI_COMMAND_REGISTER,
                    &PciCommandWord,
                    0x2);

                NdisReadPciSlotInformation(
                    Adapter->MiniportAdapterHandle,
                    Slot,
                    PCI_COMMAND_REGISTER,
                    &PciCommandWord,
                    0x2);}
            else
            {
            IF_LOUD(DbgPrint("CMD_BUS_MASTER ENABLED");)
                
            }

           
        }
    } 
	
	Adapter->NumBuffers = DEFAULT_NUMBUFFERS;
	Adapter->IoBaseAddr =(UINT)PciCardsFound.PciSlotInfo[found].BaseIo;
	Adapter->InterruptLevel= (UINT)PciCardsFound.PciSlotInfo[found].Level ;
	Adapter->InterruptVector= (UINT)PciCardsFound.PciSlotInfo[found].Vector ;
	Adapter->MulticastListMax = DEFAULT_MULTICASTLISTMAX;
	Adapter->MaxLookAhead = RTL8029_MAX_LOOKAHEAD;
    return NDIS_STATUS_SUCCESS;

}



	
	
#pragma NDIS_PAGEABLE_FUNCTION(RTL8029RegisterAdapter)
NDIS_STATUS
RTL8029RegisterAdapter(
    IN PRTL8029_ADAPTER Adapter,
    IN NDIS_HANDLE ConfigurationHandle,
    IN BOOLEAN ConfigError,
    IN ULONG ConfigErrorValue
    )

/*++

Routine Description:

    Called when a new adapter should be registered. It allocates space for
    the adapter, initializes the adapter's block, registers resources
    with the wrapper and initializes the physical adapter.

Arguments:

    Adapter - The adapter structure.

    ConfigurationHandle - Handle passed to RTL8029Initialize.

    ConfigError - Was there an error during configuration reading.

    ConfigErrorValue - Value to log if there is an error.

Return Value:

    Indicates the success or failure of the registration.

--*/

{

    //
    // Temporary looping variable.
    //
    UINT i;

    //
    // General purpose return from NDIS calls
    //
    NDIS_STATUS status;

    //
    // check that NumBuffers <= MAX_XMIT_BUFS
    //

    if (Adapter->NumBuffers > MAX_XMIT_BUFS)
        return(NDIS_STATUS_RESOURCES);

    //
    // Check for a configuration error
    //

⌨️ 快捷键说明

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