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