📄 ne2000adapter.cpp
字号:
#include "../../../include/kdndis.h"
#include "ne2000.h"
#include "ne2000adapter.h"
void NE2000RawWritePortBufferUchar(ULONG Port, PUCHAR Buffer, ULONG Length)
{
PUCHAR Current = (Buffer);
PUCHAR End = Current + Length;
for ( ; Current < End; ++Current)
{
WRITE_PORT_UCHAR((PUCHAR)Port,*(UNALIGNED UCHAR *)Current);
KeStallExecutionProcessor(1);
}
}
void NE2000RawWritePortBufferUshort(ULONG Port,PUSHORT Buffer, ULONG Length)
{
PUSHORT Current = Buffer;
PUSHORT End = Current + Length;
for ( ; Current < End; ++Current)
{
WRITE_PORT_USHORT((PUSHORT)Port,*(UNALIGNED USHORT *)Current);
KeStallExecutionProcessor(1);
}
}
void NE2000RawWritePortBufferUlong(ULONG Port,PULONG Buffer,ULONG Length)
{
PULONG Current = Buffer;
PULONG End = Current + Length;
for ( ; Current < End; ++Current)
{
WRITE_PORT_ULONG((PULONG)Port,*(UNALIGNED ULONG *)Current);
KeStallExecutionProcessor(1);
}
}
/*++
Routine Description:
Determines the type of the interrupt on the card. The order of
importance is overflow, then transmit complete, then receive.
Counter MSB is handled first since it is simple.
Arguments:
Adapter - pointer to the adapter block
InterruptStatus - Current Interrupt Status.
Return Value:
The type of the interrupt
--*/
#define CARD_GET_INTERRUPT_TYPE(_A, _I) \
(_I & ISR_COUNTER) ? \
COUNTER : \
(_I & ISR_OVERFLOW ) ? \
_A->SyncCardUpdateCounters(), OVERFLOW : \
(_I & (ISR_XMIT|ISR_XMIT_ERR)) ? \
TRANSMIT : \
(_I & ISR_RCV) ? \
RECEIVE : \
(_I & ISR_RCV_ERR) ? \
_A->SyncCardUpdateCounters(), RECEIVE : \
UNKNOWN
VOID
CardGetMulticastBit(UCHAR Address[NE2000_LENGTH_OF_ADDRESS],
UCHAR * Byte, UCHAR * Value);
UCHAR KdNe2000Adapter::BlankBuffer[] = " ";
UINT KdNe2000Adapter::Ne2000SupportedOids[] = {
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
};
KdNe2000Adapter::KdNe2000Adapter():KdNdisAdapter()
{
// Clear out the adapter block, which sets all default values to FALSE,
// or NULL.
NdisZeroMemory (&Info, sizeof(NE2000_ADAPTER));
}
KdNe2000Adapter::~KdNe2000Adapter()
{
}
/*++
Initializes the Adapter adapter and registers resources with the
wrapper.
OpenErrorStatus - Extra status bytes for opening token ring adapters.
pConf - a handle to an open configuration to be use for NdisReadConfiguration.
(it was created by the KdNdisMiniport::StaticInitializeHandler
WrapperConfigurationContext - we only need this for the NdisReadMcaPosInformation and to pass on to the adapter
Return Value:
NDIS_STATUS_SUCCESS
NDIS_STATUS_PENDING
--*/
NDIS_STATUS KdNe2000Adapter::Init(PNDIS_STATUS OpenErrorStatus, KdNdisConfiguration *pConf, NDIS_HANDLE WrapperConfigurationContext)
{
// String names of all the parameters that will be read.
PCWSTR IOAddressStr = L"IoBaseAddress";
PCWSTR InterruptStr = L"InterruptNumber";
PCWSTR MaxMulticastListStr = L"MaximumMulticastList";
PCWSTR NetworkAddressStr = L"NetworkAddress";
PCWSTR BusTypeStr = L"BusType";
PCWSTR CardTypeStr = L"CardType";
// TRUE if there is a configuration error.
BOOLEAN ConfigError = FALSE;
// A special value to log concerning the error.
ULONG ConfigErrorValue = 0;
// The slot number the adapter is located in, used for
// Microchannel adapters.
UINT SlotNumber = 0;
// TRUE if it is unnecessary to read the Io Base Address
// and Interrupt from the registry. Used for Microchannel
// adapters, which get this information from the slot
// information.
BOOLEAN SkipIobaseAndInterrupt = FALSE;
// The network address the adapter should use instead of the
// the default burned in address.
PVOID NetAddress;
// The number of bytes in the address. It should be
// NE2000_LENGTH_OF_ADDRESS
UINT Length;
// These are used when calling RegisterAdapter.
//
// The physical address of the base I/O port.
DWORD IoBaseAddr;
// The interrupt number to use.
DWORD InterruptNumber;
// The number of multicast address to be supported.
DWORD MaxMulticastList;
// Status of Ndis calls.
NDIS_STATUS Status;
// temp dword for reading from the config
DWORD ConfigReadDword;
// Read in the card type.
Status = pConf->QueryDWORD(CardTypeStr,&ConfigReadDword,NE2000_ISA);
Info.CardType = (WORD)ConfigReadDword;
// Read net address
Status = pConf->QueryNetworkAddress(&NetAddress,&Length);
if ((Length == NE2000_LENGTH_OF_ADDRESS) && (Status == NDIS_STATUS_SUCCESS))
{
// Save the address that should be used.
NdisMoveMemory(Info.StationAddress, NetAddress, NE2000_LENGTH_OF_ADDRESS);
}
// Read Bus Type (for NE2/AE2 support)
Status = pConf->QueryDWORD(BusTypeStr,&ConfigReadDword,NdisInterfaceIsa);
Info.BusType = (NDIS_INTERFACE_TYPE)ConfigReadDword;
// Read I/O Address
Status = pConf->QueryDWORD(IOAddressStr,&IoBaseAddr,DEFAULT_IOBASEADDR);
// Check that the value is valid.
if ((IoBaseAddr < MIN_IOBASEADDR) ||
(IoBaseAddr > MAX_IOBASEADDR))
{
ConfigError = TRUE;
ConfigErrorValue = (ULONG)IoBaseAddr;
goto RegisterAdapter;
}
// Read interrupt number
Status = pConf->QueryDWORD(InterruptStr,&InterruptNumber,DEFAULT_INTERRUPTNUMBER);
// Verify that the value is valid.
if ((InterruptNumber < MIN_IRQ) ||
(InterruptNumber > MAX_IRQ))
{
ConfigError = TRUE;
ConfigErrorValue = (ULONG)InterruptNumber;
goto RegisterAdapter;
}
// If the adapter is a pcmcia card then get the memory window
// address for later use.
if (NE2000_PCMCIA == Info.CardType)
{
PCWSTR AttributeMemoryAddrStr = L"PCCARDAttributeMemoryAddress";
PCWSTR AttributeMemorySizeStr = L"PCCARDAttributeMemorySize";
// Read the attribute memory address.
Status = pConf->QueryDWORD(AttributeMemoryAddrStr,&Info.AttributeMemoryAddress,0xd4000);
// Read the size of the attribute memory range.
Status = pConf->QueryDWORD(AttributeMemorySizeStr,&Info.AttributeMemorySize,0x1000);
}
// Read MaxMulticastList
Status = pConf->QueryDWORD(MaxMulticastListStr,&MaxMulticastList,DEFAULT_MULTICASTLISTMAX);
RegisterAdapter:
// Now to use this information and register with the wrapper
// and initialize the adapter.
DebugDump(DBG_LEVEL3,(
"Registering adapter # buffers %ld\n"
"Card type: 0x%x\n"
"I/O base addr 0x%lx\n"
"interrupt number %ld\n"
"max multicast %ld\nattribute memory address 0x%X\n"
"attribute memory size 0x%X\n"
"CardType: %d\n",
DEFAULT_NUMBUFFERS,
Info.CardType,
IoBaseAddr,
InterruptNumber,
DEFAULT_MULTICASTLISTMAX,
Info.AttributeMemoryAddress,
Info.AttributeMemorySize,
Info.CardType ));
// Set up the parameters.
Info.NumBuffers = DEFAULT_NUMBUFFERS;
Info.IoBaseAddr = (PVOID)IoBaseAddr;
Info.InterruptNumber = (CCHAR)InterruptNumber;
Info.MulticastListMax = MaxMulticastList;
Info.MaxLookAhead = NE2000_MAX_LOOKAHEAD;
// Now do the work.
if (Register(
WrapperConfigurationContext,
ConfigError,
ConfigErrorValue
) != NDIS_STATUS_SUCCESS)
{
return NDIS_STATUS_FAILURE;
}
DebugDump(DBG_LEVEL3, ("KdNe2000Adapter::Register succeeded\n" ));
return NDIS_STATUS_SUCCESS;
}
/*** The Handlers ****/
/*++
HaltHandler removes an adapter that was previously initialized.
--*/
VOID KdNe2000Adapter::HaltHandler()
{
// Shut down the chip.
CardStop();
// Disconnect the interrupt line.
DeregisterInterrupt();
// Pause, waiting for any DPC stuff to clear.
NdisStallExecution(250000);
DeregisterIoPortRange((ULONG)Info.IoBaseAddr,0x20,(PVOID)Info.IoPAddr);
// Remove the adapter from the global queue of adapters.
GetMiniportOwner()->RemoveAdapter(this);
delete this;
return;
}
/*++
Routine Description:
The ResetHandler request instructs the Miniport to issue a hardware reset
to the network adapter. The driver also resets its software state. See
the description of NdisMReset for a detailed description of this request.
Arguments:
AddressingReset - Does the adapter need the addressing information reloaded.
Return Value:
The function value is the status of the operation.
--*/
NDIS_STATUS KdNe2000Adapter::ResetHandler(OUT PBOOLEAN AddressingReset)
{
// Temporary looping variable
UINT i;
// Clear the values for transmits, they will be reset these for after
// the reset is completed.
Info.NextBufToFill = 0;
Info.NextBufToXmit = 0;
Info.CurBufXmitting = (XMIT_BUF)-1;
Info.FirstPacket = NULL;
Info.LastPacket = NULL;
for (i=0; i<Info.NumBuffers; i++) {
Info.BufferStatus[i] = EMPTY;
}
// Physically reset the card.
Info.NicInterruptMask = IMR_RCV | IMR_XMIT | IMR_XMIT_ERR | IMR_OVERFLOW;
return (CardReset() ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
}
/*++
Routine Description:
The QueryInformationHandler process a Query request for
NDIS_OIDs that are specific about the Driver.
Oid - the NDIS_OID to process.
InformationBuffer - a pointer into the
NdisRequest->InformationBuffer into which store the result of the query.
InformationBufferLength - a pointer to the number of bytes left in the
InformationBuffer.
BytesWritten - a pointer to the number of bytes written into the
InformationBuffer.
BytesNeeded - If there is not enough room in the information buffer
then this will contain the number of bytes needed to complete the
request.
Return Value:
The function value is the status of the operation.
--*/
NDIS_STATUS KdNe2000Adapter::QueryInformationHandler(IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesWritten,
OUT PULONG BytesNeeded)
{
// General Algorithm:
// Switch(Request)
// Get requested information
// Store results in a common variable.
// default:
// Try protocol query information
// If that fails, fail query.
//
// Copy result in common variable to result buffer.
// Finish processing
UINT BytesLeft = InformationBufferLength;
PUCHAR InfoBuffer = (PUCHAR)(InformationBuffer);
NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
NDIS_MEDIUM Medium = NdisMedium802_3;
// This variable holds result of query
ULONG GenericULong;
USHORT GenericUShort;
UCHAR GenericArray[6];
UINT MoveBytes = sizeof(ULONG);
PVOID MoveSource = (PVOID)(&GenericULong);
// Make sure that int is 4 bytes. Else GenericULong must change
// to something of size 4.
ASSERT(sizeof(ULONG) == 4);
// Switch on request type
switch (Oid)
{
case OID_GEN_MAC_OPTIONS:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -