📄 vdevadap.cpp
字号:
// VdevAdap.cpp: implementation of the VdevAdapter class.
//
//=============================================================================
//
// Compuware Corporation
// NuMega Lab
// 9 Townsend West
// Nashua, NH 03060 USA
//
// Copyright (c) 2001 Compuware Corporation. All Rights Reserved.
// Unpublished - rights reserved under the Copyright laws of the
// United States.
//
//=============================================================================
//////////////////////////////////////////////////////////////////////
#include "VdevAdap.h"
KNdisDebugTrace T("VDEV");
#define SENDBUFLENGMAX 1518
unsigned char NicSendDataBuf[SENDBUFLENGMAX];
unsigned int NicSendDataBufLength;
KMutex RWBufMutex;
////////////////
//定义写的相关变量
NDIS_HANDLE PacketPoolHandle;
int pphflag;
NDIS_HANDLE BufferPoolHandle;
int bphflag;
#define MAX_PACKET_LENGTH 1700
////////
NDIS_HANDLE pMiniHandle;
///////////////////////////
VdevAdapter *pThisVdevAdapter;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
VdevAdapter::VdevAdapter() :
KNdisMiniAdapter(), m_DeviceHandle(NULL)
{
// TODO: initialize your private data members
// Do NOT call any NDIS functions in here. Defer to Initialize()
}
VdevAdapter::~VdevAdapter()
{
// TODO: deallocate all the resources allocated in constructor/Initialize()
}
////////////////////////////////////////////////////////////////////
// NDIS callback handlers
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// VdevAdapter::Initialize
//
// MiniportInitialize is a required function that sets up a NIC (or
// virtual NIC) for network I/O operations, claims all hardware resources
// necessary to the NIC in the registry, and allocates resources the driver
// needs to carry out network I/O operations
//
// Parameters:
// Medium
// Reference to KNdisMedium object that we have to set the medium
// type our NIC supports
// Config
// Reference to KNdisConfig object that we use to query various
// configuration parameters
// IRQL:
// PASSIVE_LEVEL
// Return Mode:
// Synchronous
//
// TODO:
// 1) Select supported medium in Medium object
// 2) Read config parameters if any using Config object
// 3) Allocate h/w resources, pools, etc.
// 4) Register with NDIS using SetAttributes()
// 5) Register Shutdown Handler
// 6) Initialize and enable the NIC.
// NOTE: Be ready to process INTs even before the function exits
//
NDIS_STATUS VdevAdapter::Initialize
(IN OUT KNdisMedium& Medium, IN KNdisConfig& Config)
{
T.Trace("VdevAdapter::Initialize() Entered\n");
// Select our the Medium:
if (! Medium.Select(VDEV_MEDIUM_TYPE) )
KNDIS_RETURN_ERROR (NDIS_STATUS_UNSUPPORTED_MEDIA);
// Get network address (if any) from the Registry. If specified
// it will be used instead of burned permanent address:
if (Config.ReadNetworkAddress(m_CurrentAddress) != NDIS_STATUS_SUCCESS)
{
m_CurrentAddress.Invalidate();
}
//m_CurrentAddress.m_bytes[0] = 0x2;
// Read some other config stuff from the Registry, e.g.
ULONG uMode;
Config.Read(KNDIS_STRING_CONST("Mode"), &uMode);
// Now let NDIS know about the BUS the NIC is on. Here's where the NDIS/Adapter-instance
// handshake takes place. This should happen *before* allocating the h/w resources:
SetAttributesEx(NdisInterfaceInternal,
NDIS_ATTRIBUTE_DESERIALIZE);
// Creating "Upper" Device
// 1) Fill in the dispatch table
static PDRIVER_DISPATCH MajorFunctions[IRP_MJ_MAXIMUM_FUNCTION + 1];
NdisZeroMemory(MajorFunctions, sizeof(MajorFunctions));
MajorFunctions[IRP_MJ_CREATE] = IoCreate;
MajorFunctions[IRP_MJ_CLOSE] = IoClose;
MajorFunctions[IRP_MJ_CLEANUP] = IoCleanup;
MajorFunctions[IRP_MJ_READ] = IoRead;
MajorFunctions[IRP_MJ_WRITE] = IoWrite;
MajorFunctions[IRP_MJ_DEVICE_CONTROL] = IoDispatch;
NDIS_STATUS Status = NdisMRegisterDevice(
*KNdisMiniDriver::DriverInstance(),
KNDIS_STRING_CONST("\\Device\\MyNdisDevice"),
KNDIS_STRING_CONST("\\DosDevices\\MyNdisDevice"),
MajorFunctions,
&m_pDeviceObject,
&m_DeviceHandle);
T.Trace("VdevAdapter Create Device: %s\n", ((Status)?"FAILED":"OK"));
// TODO: Read perm address from the card instead
m_PermanentAddress = m_CurrentAddress;
// Set default filter and MAC options. In principle, we should ralso
// relay that to our card...
m_uPacketFilter = NDIS_PACKET_TYPE_DIRECTED |
NDIS_PACKET_TYPE_MULTICAST |
NDIS_PACKET_TYPE_BROADCAST;
m_uMacOptions = NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
NDIS_MAC_OPTION_NO_LOOPBACK;
// TODO: Start the card up.
RWBufMutex.Initialize(1);
/////////////////////////
pMiniHandle = m_DeviceHandle;
////////////////
NDIS_STATUS NStatus;
PacketPoolHandle = NULL;
NdisAllocatePacketPool( &NStatus, &PacketPoolHandle, 16, MAX_PACKET_LENGTH );
if( NStatus != NDIS_STATUS_SUCCESS )
{
pphflag = -1;
}
else
{
pphflag = 1;
}
BufferPoolHandle = NULL;
NdisAllocateBufferPool(&NStatus,&BufferPoolHandle,24);
if( NStatus != NDIS_STATUS_SUCCESS )
{
bphflag = -1;
}
else
{
bphflag = 1;
}
/////////////////////////
pThisVdevAdapter = this;
////////////////////////
return NDIS_STATUS_SUCCESS;
}
////////////////////////////////////////////////////////////////////
// VdevAdapter::Halt
//
// MiniportHalt is a required function that deallocates resources when
// the NIC is removed and halts the NIC.
//
// Parameters:
// None
// IRQL:
// PASSIVE_LEVEL
// Return Mode:
// Synchronous
//
// NOTE: Miniports has no "unload" for the driver. The Halt() is the last
// function called into a miniport, so everything should be stopped
// and freed right here. The KNDIS framework takes care of destroying
// the adapter object itself, so this member function is merery required
// to undo things done by the Initialize() above - in the inversed order.
//
// Alternatevely, the driver writer can move all the deallocations to the
// destructor: the destructor will be called immediatelly after Halt()
// returns. Our sample follows this practice.
//
VOID VdevAdapter::Halt(VOID)
{
T.Trace("VdevAdapter::Halt() Entered\n");
if (bphflag == 1)
NdisFreeBufferPool(BufferPoolHandle);
if (pphflag == 1)
NdisFreePacketPool(PacketPoolHandle);
if (m_DeviceHandle)
NdisMDeregisterDevice(m_DeviceHandle);
}
////////////////////////////////////////////////////////////////////
// VdevAdapter::Reset
//
// MiniportReset is a required function that issues a hardware reset
// to the NIC and/or resets the driver's software state.
//
// Parameters:
// AddressingReset
// Points to a variable that MiniportReset sets to TRUE if the
// NDIS library should call MiniportSetInformation to restore
// addressing information to the current values.
// IRQL:
// DISPATCH_LEVEL
// Return Mode:
// Asynchronous
NDIS_STATUS VdevAdapter::Reset
(OUT PBOOLEAN AddressingReset)
{
T.Trace("VdevAdapter::Reset() Entered\n");
// TODO: Reset the card
return NDIS_STATUS_SUCCESS;
}
////////////////////////////////////////////////////////////////////
// VdevAdapter::Shutdown
//
// MiniportShutdown does nothing more than restore the NIC to its
// initial state (before the miniport's DriverEntry function runs)
//
// Parameters:
// None
// IRQL:
// If MiniportShutdown is called due to a user-initiated system shutdown,
// it runs at IRQL PASSIVE_LEVEL in a system-thread context. If it is called
// due to an unrecoverable error, MiniportShutdown runs at an arbitrary IRQL
// and in the context of whatever component raised the error.
// Return Mode:
// Synchronous
VOID VdevAdapter::Shutdown(VOID)
{
T.Trace("VdevAdapter::Shutdown() Entered\n");
// TODO: Reset the card for good
}
void CopyPacket2Buffer(IN PNDIS_PACKET pPacket,IN OUT PUCHAR pBuff,IN OUT PUINT pLength)
{
PNDIS_BUFFER BuffDT;
PVOID BuffVA;
UINT BuffLen;
*pLength = 0;
BuffLen = 0;
NdisQueryPacket(pPacket,NULL,NULL,&BuffDT,NULL);
while(BuffDT != (PNDIS_BUFFER)NULL)
{
NdisQueryBuffer(BuffDT,&BuffVA,&BuffLen);
NdisMoveMemory(pBuff,BuffVA,BuffLen);
pBuff = pBuff + BuffLen;
*pLength += BuffLen;
NdisGetNextBuffer(BuffDT,&BuffDT);
}
return;
}
////////////////////////////////////////////////////////////////////
// VdevAdapter::Send
//
// Transfers a protocol-supplied packet over the network
//
// Parameters:
// Packet
// Points to a packet descriptor specifying the data to be transmitted.
// Flags
// Specifies the packet flags, if any, set by the protocol.
// IRQL:
// DISPATCH_LEVEL
// Return Mode:
// Asynchronous
// NOTE:
// The return code determines the ownership of the packet and further
// interaction between NDIS and our driver. Specifically,
//
// NDIS_STATUS_SUCCESS - Done with.
// NDIS_STATUS_PENDING - We keep it until further notice.
// NDIS_STATUS_RESOURCES - We didn't have the resouces *now*, so tell NDIS
// please hold it on until further notice.
// NOTE: Deserialized Miniports should never return NDIS_STATUS_RESOURCES to NDIS,
// and must instead queue it internally.
//
NDIS_STATUS VdevAdapter::Send(
IN PNDIS_PACKET Packet,
IN UINT Flags
)
{
T.Trace("VdevAdapter::Send() Entered\n");
T << Packet;
//NicSendDataBuf
//NicSendDataBufLength
// declare for convenience
#if 0
KNdisPacket pkt(Packet);
KNdisBuffer buf;
UINT size;
PUCHAR Buffer;
#endif
// RWBufMutex.Wait();
NicSendDataBufLength = 0;
CopyPacket2Buffer(Packet,NicSendDataBuf,&NicSendDataBufLength);
for (UINT i = 0 ;i < NicSendDataBufLength; i ++)
{
T.Trace("[%02x]",NicSendDataBuf[i]);
}
m_GenStats->xmit_ok++;
return NDIS_STATUS_SUCCESS;
#if 0
buf = pkt.QueryFirstBuffer();
while(buf.IsValid())
{
size = buf.Length();
T.Trace("VdevAdapter::Send size is [%ud]\n",size);
Buffer = (PUCHAR)buf.Address();
if (Buffer != NULL) {
if (size > 1)
{
memcpy(NicSendDataBuf + NicSendDataBufLength,Buffer,size);
NicSendDataBufLength = NicSendDataBufLength + size;
if (NicSendDataBufLength > SENDBUFLENGMAX)
{
NicSendDataBufLength = SENDBUFLENGMAX;
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -