📄 d100.c
字号:
/****************************************************************************
** COPYRIGHT (C) 1994-1997 INTEL CORPORATION **
** DEVELOPED FOR MICROSOFT BY INTEL CORP., HILLSBORO, OREGON **
** HTTP://WWW.INTEL.COM/ **
** THIS FILE IS PART OF THE INTEL ETHEREXPRESS PRO/100B(TM) AND **
** ETHEREXPRESS PRO/100+(TM) NDIS 5.0 MINIPORT SAMPLE DRIVER **
****************************************************************************/
/****************************************************************************
Module Name:
d100.c
This driver runs on the following hardware:
- 82557/82558 based PCI 10/100Mb ethernet adapters
(aka Intel EtherExpress(TM) PRO Adapters)
Environment:
Kernel Mode - Or whatever is the equivalent on WinNT
Revision History
- JCB 8/14/97 Example Driver Created
*****************************************************************************/
#include "precomp.h"
#pragma hdrstop
#pragma warning (disable: 4244 4514 4706)
//-----------------------------------------------------------------------------
// Procedure: DeleteSharedAdapterMemory
//
// Description: This routine is responsible for the deallocation of the
// shared memory data structures for the Adapter structure. This
// includes the both the cached and uncached memory allocations.
// We also free any allocated map registers in this routine.
//
// Arguments:
// Adapter - Ptr to the Adapter structure
//
// Returns: (none)
//-----------------------------------------------------------------------------
VOID
DeleteSharedAdapterMemory(PD100_ADAPTER Adapter)
{
#if DBG
UINT RfdNum;
#endif
UINT count;
D100SwRfd *SwRfdPtr;
DEBUGFUNC("DeleteSharedAdapterMemory");
INITSTR(("\n"));
// Free memory for receive packetpool and bufferpool
if (Adapter->ReceivePacketPool)
{
TRACESTR(Adapter,("Freeing Packet Pool resources\n"));
// get the first one to free
SwRfdPtr = (D100SwRfd *) QueuePopHead(&Adapter->RfdList); // cached RFDs logical
#if DBG
count = 0;
#endif
while (SwRfdPtr != (PD100SwRfd) 0)
{
FreeSwRfd(Adapter,SwRfdPtr);
// walk our list of receive packets
SwRfdPtr = (PD100SwRfd) QueuePopHead(&Adapter->RfdList);
#if DBG
++count;
#endif
}
#if DBG
// assert if we didnt free the full number of Rfds
ASSERT(count == Adapter->NumRfd);
// assert if our pool isnt empty
// RfdNum = NdisPacketPoolUsage(Adapter->ReceivePacketPool);
// ASSERT(!RfdNum);
#endif
NdisFreeBufferPool(Adapter->ReceiveBufferPool);
NdisFreePacketPool(Adapter->ReceivePacketPool);
}
// go through each element in our array and free the memory
// pointed to by the element
for (count = 0; count < NUM_RMD ; ++count)
{
// the packets and buffers should have already been freed
// if a virtual address exists, we have to free the unit
if (Adapter->ReceiveMemoryDescArray[count].CachedMem.VirtualAddress)
{
FreeRMD(Adapter,&Adapter->ReceiveMemoryDescArray[count]);
}
}
// Free any memory allocated for the Original Software
// receive structures (SwRfds)
if (Adapter->RecvCached)
{
TRACESTR(Adapter, ("Freeing %d bytes RecvCached\n", Adapter->RecvCachedSize));
NdisFreeMemory((PVOID) Adapter->RecvCached, Adapter->RecvCachedSize, 0);
Adapter->RecvCached = (PUCHAR) 0;
}
// Free any memory allocated for the shared receive structures (RFDs)
// the original ones...
if (Adapter->RecvUnCached)
{
TRACESTR(Adapter, ("Freeing %d bytes RecvUnCached\n", Adapter->RecvUnCachedSize));
// Now free the shared memory that was used for the receive buffers.
NdisMFreeSharedMemory(
Adapter->D100AdapterHandle,
Adapter->RecvUnCachedSize,
FALSE,
(PVOID) Adapter->RecvUnCached,
Adapter->RecvUnCachedPhys);
Adapter->RecvUnCached = (PUCHAR) 0;
}
// Free any memory allocated for the Software transmit structures (SwTcbs)
if (Adapter->XmitCached)
{
TRACESTR(Adapter, ("Freeing %d bytes XmitCached\n", Adapter->XmitCachedSize));
NdisFreeMemory((PVOID) Adapter->XmitCached, Adapter->XmitCachedSize, 0);
Adapter->XmitCached = (PUCHAR) 0;
}
// Free any memory allocated for the shared transmit structures (TCBs,
// TBDs, non transmit command blocks, etc.)
if (Adapter->CbUnCached)
{
TRACESTR(Adapter, ("Freeing %d bytes XmitUnCached\n", Adapter->CbUnCachedSize));
// Now free the shared memory that was used for the command blocks and
// transmit buffers.
NdisMFreeSharedMemory(
Adapter->D100AdapterHandle,
Adapter->CbUnCachedSize,
FALSE,
(PVOID) Adapter->CbUnCached,
Adapter->CbUnCachedPhys
);
Adapter->CbUnCached = (PUCHAR) 0;
Adapter->XmitUnCached = (PUCHAR) 0;
}
// If this is a miniport driver we must free our allocated map registers
if (Adapter->NumMapRegisters)
{
NdisMFreeMapRegisters(Adapter->D100AdapterHandle);
}
}
//-----------------------------------------------------------------------------
// Procedure: FreeAdapterObject
//
// Description: This routine releases all resources defined in the ADAPTER
// object and returns the ADAPTER object memory to the free pool.
//
// Arguments:
// Adapter - ptr to Adapter object instance
//
// Returns: (none)
//-----------------------------------------------------------------------------
VOID
FreeAdapterObject(PD100_ADAPTER Adapter)
{
DEBUGFUNC("FreeAdapterObject");
INITSTR(("\n"));
// Free the transmit, receive, and SCB structures
DeleteSharedAdapterMemory(Adapter);
// we must delete any IO mappings that we have registered
if (Adapter->MappedIoBase)
{
NdisMDeregisterIoPortRange(
Adapter->D100AdapterHandle,
(UINT) Adapter->AiBaseIo,
Adapter->MappedIoRange,
(PVOID) Adapter->MappedIoBase);
}
// free the adapter object itself
D100_FREE_MEM(Adapter, sizeof(D100_ADAPTER));
}
//-----------------------------------------------------------------------------
// Procedure: SoftwareReset
//
// Description: This routine is called by SelfTestHardware and InitializeD100.
// It resets the D100 by issuing a PORT SOFTWARE RESET.
//
// Arguments:
// Adapter - ptr to Adapter object instance
//
// Returns:
// (none)
//-----------------------------------------------------------------------------
VOID
SoftwareReset(PD100_ADAPTER Adapter)
{
DEBUGFUNC("SoftWareReset");
INITSTR(("\n"));
DEBUGCHAR(Adapter,'W');
// Issue a PORT command with a data word of 0
Adapter->CSRAddress->Port = PORT_SOFTWARE_RESET;
// wait 20 milliseconds for the reset to take effect
D100StallExecution(20);
// Mask off our interrupt line -- its unmasked after reset
D100DisableInterrupt(Adapter);
}
//-----------------------------------------------------------------------------
// Procedure: DriverEntry
//
// Description: This is the primary initialization routine for the D100
// driver. It is simply responsible for the intializing the
// wrapper and registering the adapter driver. The routine gets
// called once per driver, but D100Initialize(miniport) or
// AddAdapter (mac) 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
//-----------------------------------------------------------------------------
NTSTATUS
DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath)
{
NDIS_STATUS Status;
NDIS_HANDLE NdisWrapperHandle;
NDIS_MINIPORT_CHARACTERISTICS D100Char;
DEBUGFUNC("D100DriverEntry");
INITSTR(("\n"));
// Now we must initialize the wrapper, and then register the Miniport
NdisMInitializeWrapper( &NdisWrapperHandle,
DriverObject,
RegistryPath,
NULL
);
NdisZeroMemory(&D100Char, sizeof(D100Char));
// Initialize the Miniport characteristics for the call to
// NdisMRegisterMiniport.
D100Char.MajorNdisVersion = D100_NDIS_MAJOR_VERSION;
D100Char.MinorNdisVersion = D100_NDIS_MINOR_VERSION;
D100Char.CheckForHangHandler = D100CheckForHang;
D100Char.DisableInterruptHandler= D100DisableInterrupt;
D100Char.EnableInterruptHandler = D100EnableInterrupt;
D100Char.HaltHandler = D100Halt;
D100Char.HandleInterruptHandler = D100HandleInterrupt;
D100Char.InitializeHandler = D100Initialize;
D100Char.ISRHandler = D100Isr;
D100Char.QueryInformationHandler= D100QueryInformation;
D100Char.ReconfigureHandler = NULL;
D100Char.ResetHandler = D100Reset;
D100Char.SetInformationHandler = D100SetInformation;
D100Char.SendHandler = NULL;
D100Char.SendPacketsHandler = D100MultipleSend;
D100Char.ReturnPacketHandler = D100GetReturnedPackets;
D100Char.TransferDataHandler = NULL;
D100Char.AllocateCompleteHandler = D100AllocateComplete;
DEBUGSTR(("DriverEntry: About to call NdisMRegisterMiniport\n"));
// Register this driver with the NDIS wrapper
// This will cause D100Initialize to be called before returning
Status = NdisMRegisterMiniport(
NdisWrapperHandle,
&D100Char,
sizeof(NDIS_MINIPORT_CHARACTERISTICS));
DEBUGSTR(("DriverEntry: NdisMRegisterMiniport returns %X\n", Status));
if (Status == NDIS_STATUS_SUCCESS)
return STATUS_SUCCESS;
DEBUGSTR(("NdisMRegisterMiniport failed (Status = 0x%x)\n", Status));
return Status;
}
//-----------------------------------------------------------------------------
// D100GetReturnedPackets
//
// PARAMETERS: IN NDIS_HANDLE MiniportAdapterContext
// - a context version of our Adapter pointer
// IN NDIS_PACKET Packet
// - the packet that is being freed
//
// DESCRIPTION: This function attempts to return to the receive free list the
// packet passed to us by NDIS
//
// RETURNS: nothing
//
//-----------------------------------------------------------------------------
VOID
D100GetReturnedPackets(NDIS_HANDLE MiniportAdapterContext,
PNDIS_PACKET Packet)
{
PD100_ADAPTER Adapter;
PD100SwRfd SwRfd;
DEBUGFUNC("D100GetReturnedPackets");
Adapter = PD100_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
NdisAcquireSpinLock(&Adapter->Lock);
TRACE2(Adapter, ("\n"));
ASSERT(Packet);
DEBUGCHAR(Adapter,'G');
SwRfd = *(D100SwRfd **)(Packet->MiniportReserved);
ASSERT(SwRfd);
InitAndChainPacket(Adapter, SwRfd);
--Adapter->UsedRfdCount;
ASSERT(Adapter->UsedRfdCount <= Adapter->NumRfd);
NdisReleaseSpinLock(&Adapter->Lock);
return;
}
//-----------------------------------------------------------------------------
// PROCEDURE: InitAndChainPacket
//
// PARAMETERS: Adapter structure Pointer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -