mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2077 lines
46 KiB
2077 lines
46 KiB
/*++
|
|
|
|
Copyright (c) 1990-1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
configm.c
|
|
|
|
Abstract:
|
|
|
|
NDIS wrapper functions for miniport configuration/initialization
|
|
|
|
Author:
|
|
|
|
Sean Selitrennikoff (SeanSe) 05-Oct-93
|
|
Jameel Hyder (JameelH) 01-Jun-95
|
|
|
|
Environment:
|
|
|
|
Kernel mode, FSD
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <precomp.h>
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// Define the module number for debug code.
|
|
//
|
|
#define MODULE_NUMBER MODULE_CONFIGM
|
|
|
|
|
|
NDIS_STATUS
|
|
NdisMRegisterMiniport(
|
|
IN NDIS_HANDLE NdisWrapperHandle,
|
|
IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
|
|
IN UINT CharacteristicsLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Used to register a Miniport driver with the wrapper.
|
|
|
|
Arguments:
|
|
|
|
Status - Status of the operation.
|
|
|
|
NdisWrapperHandle - Handle returned by NdisWInitializeWrapper.
|
|
|
|
MiniportCharacteritics - The NDIS_MINIPORT_CHARACTERISTICS table.
|
|
|
|
CharacteristicsLength - The length of MiniportCharacteristics.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_STATUS Status;
|
|
PNDIS_M_DRIVER_BLOCK MiniBlock;
|
|
PNDIS_WRAPPER_HANDLE DriverInfo = (PNDIS_WRAPPER_HANDLE)(NdisWrapperHandle);
|
|
|
|
Status = NdisIMRegisterLayeredMiniport(NdisWrapperHandle,
|
|
MiniportCharacteristics,
|
|
CharacteristicsLength,
|
|
&MiniBlock);
|
|
|
|
DBGPRINT(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
|
|
("Exit mini-port register\n"));
|
|
|
|
if (Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
InitReferencePackage();
|
|
if (DriverInfo->NdisWrapperConfigurationHandle)
|
|
{
|
|
Status = ndisInitializeAllAdapterInstances((PNDIS_MAC_BLOCK)MiniBlock, NULL);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
ndisDereferenceDriver(MiniBlock);
|
|
Status = NDIS_STATUS_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = NDIS_STATUS_FAILURE;
|
|
}
|
|
InitDereferencePackage();
|
|
}
|
|
|
|
ASSERT (CURRENT_IRQL < DISPATCH_LEVEL);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
NdisIMRegisterLayeredMiniport(
|
|
IN NDIS_HANDLE NdisWrapperHandle,
|
|
IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
|
|
IN UINT CharacteristicsLength,
|
|
OUT PNDIS_HANDLE DriverHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Used to register a layered Miniport driver with the wrapper.
|
|
|
|
Arguments:
|
|
|
|
Status - Status of the operation.
|
|
|
|
NdisWrapperHandle - Handle returned by NdisWInitializeWrapper.
|
|
|
|
MiniportCharacteritics - The NDIS_MINIPORT_CHARACTERISTICS table.
|
|
|
|
CharacteristicsLength - The length of MiniportCharacteristics.
|
|
|
|
DriverHandle - Returns a handle which can be used to call NdisMInitializeDeviceInstance.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_M_DRIVER_BLOCK MiniBlock;
|
|
PNDIS_WRAPPER_HANDLE DriverInfo = (PNDIS_WRAPPER_HANDLE)(NdisWrapperHandle);
|
|
UNICODE_STRING Us;
|
|
PWSTR pWch;
|
|
USHORT i, size;
|
|
UINT MemNeeded;
|
|
NDIS_STATUS Status;
|
|
KIRQL OldIrql;
|
|
|
|
DBGPRINT(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
|
|
("Enter mini-port register\n"));
|
|
|
|
do
|
|
{
|
|
if (DriverInfo == NULL)
|
|
{
|
|
Status = NDIS_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Check version numbers and CharacteristicsLength.
|
|
//
|
|
|
|
size = 0; // Used to indicate bad version below
|
|
if (MiniportCharacteristics->MajorNdisVersion == 3)
|
|
{
|
|
if (MiniportCharacteristics->MinorNdisVersion == 0)
|
|
size = sizeof(NDIS30_MINIPORT_CHARACTERISTICS);
|
|
}
|
|
|
|
else if (MiniportCharacteristics->MajorNdisVersion == 4)
|
|
{
|
|
if (MiniportCharacteristics->MinorNdisVersion == 0)
|
|
{
|
|
size = sizeof(NDIS40_MINIPORT_CHARACTERISTICS);
|
|
}
|
|
else if (MiniportCharacteristics->MinorNdisVersion == 1)
|
|
{
|
|
size = sizeof(NDIS41_MINIPORT_CHARACTERISTICS);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check that this is an NDIS 3.0/4.0/4.1 miniport.
|
|
//
|
|
if (size == 0)
|
|
{
|
|
Status = NDIS_STATUS_BAD_VERSION;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Check that CharacteristicsLength is enough.
|
|
//
|
|
if (CharacteristicsLength < size)
|
|
{
|
|
Status = NDIS_STATUS_BAD_CHARACTERISTICS;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for the NDIS MINIPORT block.
|
|
//
|
|
MemNeeded = sizeof(NDIS_M_DRIVER_BLOCK);
|
|
|
|
//
|
|
// Extract the base-name, determine its length and allocate that much more
|
|
//
|
|
Us = *(PUNICODE_STRING)(DriverInfo->NdisWrapperConfigurationHandle);
|
|
|
|
for (i = Us.Length/sizeof(WCHAR), pWch = Us.Buffer + i - 1;
|
|
i > 0;
|
|
pWch --, i--)
|
|
{
|
|
if (*pWch == L'\\')
|
|
{
|
|
Us.Buffer = pWch + 1;
|
|
Us.Length -= i*sizeof(WCHAR);
|
|
Us.MaximumLength = Us.Length + sizeof(WCHAR);
|
|
break;
|
|
}
|
|
}
|
|
MemNeeded += Us.MaximumLength;
|
|
|
|
MiniBlock = (PNDIS_M_DRIVER_BLOCK)ALLOC_FROM_POOL(MemNeeded, NDIS_TAG_MINI_BLOCK);
|
|
|
|
if (MiniBlock == (PNDIS_M_DRIVER_BLOCK)NULL)
|
|
{
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
ZeroMemory(MiniBlock, MemNeeded);
|
|
|
|
MiniBlock->Length = MemNeeded;
|
|
|
|
//
|
|
// Copy over the characteristics table.
|
|
//
|
|
|
|
CopyMemory(&MiniBlock->MiniportCharacteristics,
|
|
MiniportCharacteristics,
|
|
size);
|
|
|
|
//
|
|
// Upcase the base-name and save it in the MiniBlock
|
|
//
|
|
MiniBlock->BaseName.Buffer = (PWSTR)((PUCHAR)MiniBlock + sizeof(NDIS_M_DRIVER_BLOCK));
|
|
MiniBlock->BaseName.Length =
|
|
MiniBlock->BaseName.MaximumLength = Us.Length;
|
|
RtlUpcaseUnicodeString(&MiniBlock->BaseName,
|
|
&Us,
|
|
FALSE);
|
|
//
|
|
// No adapters yet registered for this Miniport.
|
|
//
|
|
|
|
MiniBlock->MiniportQueue = (PNDIS_MINIPORT_BLOCK)NULL;
|
|
|
|
//
|
|
// Set up unload handler
|
|
//
|
|
|
|
DriverInfo->NdisWrapperDriver->DriverUnload = ndisMUnload;
|
|
|
|
//
|
|
// Set up shutdown handler
|
|
//
|
|
DriverInfo->NdisWrapperDriver->MajorFunction[IRP_MJ_SHUTDOWN] = ndisMShutdown;
|
|
|
|
//
|
|
// Set up the handlers for this driver (they all do nothing).
|
|
//
|
|
|
|
DriverInfo->NdisWrapperDriver->MajorFunction[IRP_MJ_CREATE] = ndisCreateIrpHandler;
|
|
DriverInfo->NdisWrapperDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ndisDeviceControlIrpHandler;
|
|
DriverInfo->NdisWrapperDriver->MajorFunction[IRP_MJ_CLEANUP] = ndisSuccessIrpHandler;
|
|
DriverInfo->NdisWrapperDriver->MajorFunction[IRP_MJ_CLOSE] = ndisCloseIrpHandler;
|
|
|
|
//
|
|
// Use this event to tell us when all adapters are removed from the mac
|
|
// during an unload
|
|
//
|
|
INITIALIZE_EVENT(&MiniBlock->MiniportsRemovedEvent);
|
|
|
|
MiniBlock->Unloading = FALSE;
|
|
MiniBlock->NdisDriverInfo = DriverInfo;
|
|
MiniBlock->MiniportIdField = (NDIS_HANDLE)0x1;
|
|
|
|
NdisInitializeRef(&MiniBlock->Ref);
|
|
|
|
// Lock the init code down now - before we take the lock below
|
|
MiniportReferencePackage();
|
|
|
|
//
|
|
// Put Driver on global list.
|
|
//
|
|
ACQUIRE_SPIN_LOCK(&ndisDriverListLock, &OldIrql);
|
|
|
|
MiniBlock->NextDriver = ndisMiniDriverList;
|
|
ndisMiniDriverList = MiniBlock;
|
|
|
|
RELEASE_SPIN_LOCK(&ndisDriverListLock, OldIrql);
|
|
|
|
MiniportDereferencePackage();
|
|
|
|
*DriverHandle = MiniBlock;
|
|
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
} while (FALSE);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
NdisIMDeInitializeDeviceInstance(
|
|
IN NDIS_HANDLE NdisMiniportHandle
|
|
)
|
|
{
|
|
PNDIS_MINIPORT_BLOCK Miniport;
|
|
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
|
|
|
|
Miniport = (PNDIS_MINIPORT_BLOCK)NdisMiniportHandle;
|
|
|
|
if (ndisReferenceMiniport(Miniport))
|
|
{
|
|
Status = ndisUnloadMiniport(Miniport);
|
|
ndisDereferenceMiniport(Miniport);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
ndisMOpenAdapter(
|
|
OUT PNDIS_STATUS Status,
|
|
OUT PNDIS_STATUS OpenErrorStatus,
|
|
OUT PNDIS_HANDLE NdisBindingHandle,
|
|
IN NDIS_HANDLE NdisProtocolHandle,
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN PNDIS_STRING AdapterName,
|
|
IN UINT OpenOptions,
|
|
IN PSTRING AddressingInformation,
|
|
IN PNDIS_MINIPORT_BLOCK Miniport,
|
|
IN PNDIS_OPEN_BLOCK NewOpenP,
|
|
IN PFILE_OBJECT FileObject,
|
|
IN BOOLEAN UsingEncapsulation
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles opening a miniport either directly from NdisOpenAdapter()
|
|
of from our deferred processing routine if the open had to pend.
|
|
|
|
NOTE: Must be called with spin lock held.
|
|
NOTE: Must be called with lock acquired flag set.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PNDIS_M_OPEN_BLOCK MiniportOpen;
|
|
PNDIS_MAC_BLOCK FakeMac;
|
|
BOOLEAN FilterOpen;
|
|
PNDIS_PROTOCOL_BLOCK TmpProtP;
|
|
BOOLEAN DerefMini = FALSE, FreeOpen = FALSE,
|
|
DerefProt = FALSE;
|
|
|
|
ASSERT(MINIPORT_LOCK_ACQUIRED(Miniport));
|
|
|
|
do
|
|
{
|
|
if (!ndisReferenceMiniport(Miniport))
|
|
{
|
|
//
|
|
// The adapter is closing.
|
|
//
|
|
*Status = NDIS_STATUS_CLOSING;
|
|
break;
|
|
}
|
|
DerefMini = TRUE;
|
|
|
|
//
|
|
// Increment the protocol's reference count.
|
|
//
|
|
TmpProtP = (PNDIS_PROTOCOL_BLOCK)NdisProtocolHandle;
|
|
|
|
if (!ndisReferenceProtocol(TmpProtP))
|
|
{
|
|
//
|
|
// The protocol is closing.
|
|
//
|
|
*Status = NDIS_STATUS_CLOSING;
|
|
break;
|
|
}
|
|
DerefProt = TRUE;
|
|
|
|
//
|
|
// Now allocate a complete set of MAC structures for the protocol
|
|
// and set them up to transfer to the Miniport handler routines.
|
|
//
|
|
if (Miniport->FakeMac == NULL)
|
|
{
|
|
//
|
|
// Allocate a fake MAC block for the characteristics.
|
|
//
|
|
FakeMac = (PNDIS_MAC_BLOCK)ALLOC_FROM_POOL(sizeof(NDIS_MAC_BLOCK), NDIS_TAG_DEFAULT);
|
|
if (FakeMac == NULL)
|
|
{
|
|
*Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Initialize the fake mac block.
|
|
//
|
|
ZeroMemory(FakeMac, sizeof(NDIS_MAC_BLOCK));
|
|
|
|
//
|
|
// Save the fake mac block with the miniport.
|
|
//
|
|
Miniport->FakeMac = FakeMac;
|
|
|
|
//
|
|
// If transfer data calls don't pend then we'll use the faster
|
|
// ndisMTransferDataSync().
|
|
//
|
|
if ((Miniport->MacOptions & NDIS_MAC_OPTION_TRANSFERS_NOT_PEND) != 0)
|
|
{
|
|
FakeMac->MacCharacteristics.TransferDataHandler = ndisMTransferDataSync;
|
|
}
|
|
else
|
|
{
|
|
FakeMac->MacCharacteristics.TransferDataHandler = ndisMTransferData;
|
|
}
|
|
|
|
//
|
|
// Initialize the reset handler.
|
|
//
|
|
FakeMac->MacCharacteristics.ResetHandler = ndisMReset;
|
|
|
|
//
|
|
// Initialize the request handler.
|
|
//
|
|
FakeMac->MacCharacteristics.RequestHandler = ndisMRequest;
|
|
|
|
//
|
|
// Initialize the send handler.
|
|
//
|
|
switch (Miniport->MediaType)
|
|
{
|
|
case NdisMediumArcnet878_2:
|
|
|
|
FakeMac->MacCharacteristics.SendHandler = ndisMArcnetSend;
|
|
break;
|
|
|
|
case NdisMediumWan:
|
|
|
|
FakeMac->MacCharacteristics.SendHandler = (PVOID)ndisMWanSend;
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// If this is a fullduplex miniport then change the reset handler.
|
|
//
|
|
if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_FULL_DUPLEX))
|
|
{
|
|
FakeMac->MacCharacteristics.ResetHandler = ndisMResetFullDuplex;
|
|
}
|
|
|
|
//
|
|
// Set up the send packet handlers miniports that support
|
|
// the new NDIS 4.0 SendPackets handler.
|
|
//
|
|
if (MINIPORT_TEST_SEND_FLAG(Miniport, fMINIPORT_SEND_PACKET_ARRAY))
|
|
{
|
|
if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_FULL_DUPLEX))
|
|
{
|
|
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
|
|
("Using ndisMSendFullDuplexToSendPackets\n"));
|
|
FakeMac->MacCharacteristics.SendHandler = ndisMSendFullDuplexToSendPackets;
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
|
|
("Using ndisMSendToSendPackets\n"));
|
|
FakeMac->MacCharacteristics.SendHandler = ndisMSendToSendPackets;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_FULL_DUPLEX))
|
|
{
|
|
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
|
|
("Using ndisMSendFullDuplex\n"));
|
|
FakeMac->MacCharacteristics.SendHandler = ndisMSendFullDuplex;
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
|
|
("Using ndisMSend\n"));
|
|
FakeMac->MacCharacteristics.SendHandler = ndisMSend;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If the miniport indicates packets the we have a dummy
|
|
// transfer data.
|
|
//
|
|
if (Miniport->DriverHandle->MiniportCharacteristics.ReturnPacketHandler != NULL)
|
|
{
|
|
// This driver supports the receive packet paradigm
|
|
// Fake the transferdata handler so if any xport calls
|
|
// this, we're still ok
|
|
FakeMac->MacCharacteristics.TransferDataHandler = ndisMDummyTransferData;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FakeMac = Miniport->FakeMac;
|
|
}
|
|
|
|
//
|
|
// Allocate an open within the Miniport context
|
|
//
|
|
MiniportOpen = (PNDIS_M_OPEN_BLOCK)ALLOC_FROM_POOL(sizeof(NDIS_M_OPEN_BLOCK), NDIS_TAG_DEFAULT);
|
|
if (MiniportOpen == (PNDIS_M_OPEN_BLOCK)NULL)
|
|
{
|
|
*Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
FreeOpen = TRUE;
|
|
|
|
//
|
|
// Initialize the open block.
|
|
//
|
|
ZeroMemory(MiniportOpen, sizeof(NDIS_M_OPEN_BLOCK));
|
|
|
|
MiniportOpen->DriverHandle = Miniport->DriverHandle;
|
|
MiniportOpen->MiniportHandle = Miniport;
|
|
MiniportOpen->ProtocolHandle = TmpProtP;
|
|
MiniportOpen->FakeOpen = NewOpenP;
|
|
MiniportOpen->ProtocolBindingContext = ProtocolBindingContext;
|
|
MiniportOpen->MiniportAdapterContext = Miniport->MiniportAdapterContext;
|
|
MiniportOpen->FileObject = FileObject;
|
|
MiniportOpen->CurrentLookahead = Miniport->CurrentLookahead;
|
|
|
|
NdisAllocateSpinLock(&(MiniportOpen->SpinLock));
|
|
|
|
DBGPRINT(DBG_COMP_OPEN, DBG_LEVEL_INFO, ("=1 0x%x\n", MiniportOpen));
|
|
|
|
MiniportOpen->References = 1;
|
|
|
|
if (UsingEncapsulation)
|
|
{
|
|
MINIPORT_SET_FLAG(MiniportOpen, fMINIPORT_OPEN_USING_ETH_ENCAPSULATION);
|
|
}
|
|
|
|
//
|
|
// Save the handlers with the open block.
|
|
//
|
|
MiniportOpen->SendHandler = Miniport->DriverHandle->MiniportCharacteristics.SendHandler;
|
|
MiniportOpen->TransferDataHandler = Miniport->DriverHandle->MiniportCharacteristics.TransferDataHandler;
|
|
MiniportOpen->SendCompleteHandler = TmpProtP->ProtocolCharacteristics.SendCompleteHandler;
|
|
MiniportOpen->TransferDataCompleteHandler = TmpProtP->ProtocolCharacteristics.TransferDataCompleteHandler;
|
|
MiniportOpen->ReceiveHandler = TmpProtP->ProtocolCharacteristics.ReceiveHandler;
|
|
MiniportOpen->ReceiveCompleteHandler = TmpProtP->ProtocolCharacteristics.ReceiveCompleteHandler;
|
|
|
|
//
|
|
// NDIS 4.0 miniport extensions
|
|
//
|
|
MiniportOpen->SendPacketsHandler = Miniport->DriverHandle->MiniportCharacteristics.SendPacketsHandler;
|
|
|
|
//
|
|
// NDIS 4.0 protocol extensions
|
|
//
|
|
MiniportOpen->ReceivePacketHandler =
|
|
(Miniport->DriverHandle->MiniportCharacteristics.ReturnPacketHandler == NULL) ?
|
|
NULL :
|
|
TmpProtP->ProtocolCharacteristics.ReceivePacketHandler;
|
|
|
|
//
|
|
// NDIS 4.1 miniport extensions
|
|
//
|
|
MiniportOpen->MiniportCoRequestHandler = Miniport->DriverHandle->MiniportCharacteristics.CoRequestHandler;
|
|
MiniportOpen->MiniportCoCreateVcHandler = Miniport->DriverHandle->MiniportCharacteristics.CoCreateVcHandler;
|
|
|
|
//
|
|
// NDIS 4.1 protocol extensions
|
|
//
|
|
MiniportOpen->CoRequestCompleteHandler =
|
|
TmpProtP->ProtocolCharacteristics.CoRequestCompleteHandler;
|
|
|
|
//
|
|
// initialize Lists
|
|
//
|
|
InitializeListHead(&MiniportOpen->ActiveVcHead);
|
|
InitializeListHead(&MiniportOpen->InactiveVcHead);
|
|
|
|
//
|
|
// Set up the elements of the open structure.
|
|
//
|
|
INITIALIZE_SPIN_LOCK(&NewOpenP->SpinLock);
|
|
NewOpenP->Closing = FALSE;
|
|
|
|
NewOpenP->AdapterHandle = (NDIS_HANDLE) Miniport;
|
|
NewOpenP->ProtocolHandle = TmpProtP;
|
|
NewOpenP->ProtocolBindingContext = ProtocolBindingContext;
|
|
NewOpenP->MacBindingHandle = (NDIS_HANDLE)MiniportOpen;
|
|
|
|
//
|
|
// for speed, instead of having to use AdapterHandle->MacHandle
|
|
//
|
|
NewOpenP->MacHandle = (NDIS_HANDLE)FakeMac;
|
|
|
|
//
|
|
// for even more speed...
|
|
//
|
|
if (NdisMediumArcnet878_2 == Miniport->MediaType)
|
|
{
|
|
NewOpenP->TransferDataHandler = ndisMArcTransferData;
|
|
}
|
|
else
|
|
{
|
|
NewOpenP->TransferDataHandler = FakeMac->MacCharacteristics.TransferDataHandler;
|
|
}
|
|
|
|
//
|
|
// Set the send handler in the open block.
|
|
//
|
|
NewOpenP->SendHandler = FakeMac->MacCharacteristics.SendHandler;
|
|
NewOpenP->RequestHandler = ndisMRequest;
|
|
|
|
//
|
|
// Set up the send packets handler.
|
|
//
|
|
if (MINIPORT_TEST_SEND_FLAG(Miniport, fMINIPORT_SEND_PACKET_ARRAY))
|
|
{
|
|
if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_FULL_DUPLEX))
|
|
{
|
|
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
|
|
("Using ndisMSendPacketsFullDuplex\n"));
|
|
NewOpenP->SendPacketsHandler = ndisMSendPacketsFullDuplex;
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
|
|
("Using ndisMSendPackets\n"));
|
|
NewOpenP->SendPacketsHandler = ndisMSendPackets;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_FULL_DUPLEX))
|
|
{
|
|
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
|
|
("Using ndisMSendPacketsFullDuplexToSend\n"));
|
|
NewOpenP->SendPacketsHandler = ndisMSendPacketsFullDuplexToSend;
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
|
|
("Using ndisMSendPacketsToSend\n"));
|
|
NewOpenP->SendPacketsHandler = ndisMSendPacketsToSend;
|
|
}
|
|
}
|
|
|
|
//
|
|
// For WAN miniports, the send handler is different.
|
|
//
|
|
if (NdisMediumWan == Miniport->MediaType)
|
|
{
|
|
NewOpenP->SendHandler = (PVOID)ndisMWanSend;
|
|
}
|
|
else if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO))
|
|
{
|
|
//
|
|
// the convential send function is not available for CO miniports
|
|
// since this send function does not specify the Vc to send upon
|
|
// However for components which want to use this let them.
|
|
//
|
|
if ((NewOpenP->SendHandler == NULL) && (NewOpenP->SendPacketsHandler == NULL))
|
|
{
|
|
NewOpenP->SendHandler = ndisMRejectSend;
|
|
FakeMac->MacCharacteristics.SendHandler = ndisMRejectSend;
|
|
}
|
|
|
|
//
|
|
// Trap the conventional request handlers if they are not specified.
|
|
//
|
|
if ((Miniport->DriverHandle->MiniportCharacteristics.SetInformationHandler == NULL) ||
|
|
(Miniport->DriverHandle->MiniportCharacteristics.QueryInformationHandler == NULL))
|
|
{
|
|
FakeMac->MacCharacteristics.RequestHandler = ndisMWrappedRequest;
|
|
NewOpenP->RequestHandler = ndisMWrappedRequest;
|
|
}
|
|
}
|
|
|
|
NewOpenP->SendCompleteHandler = TmpProtP->ProtocolCharacteristics.SendCompleteHandler;
|
|
NewOpenP->TransferDataCompleteHandler = TmpProtP->ProtocolCharacteristics.TransferDataCompleteHandler;
|
|
NewOpenP->ReceiveHandler = TmpProtP->ProtocolCharacteristics.ReceiveHandler;
|
|
NewOpenP->ReceiveCompleteHandler = TmpProtP->ProtocolCharacteristics.ReceiveCompleteHandler;
|
|
NewOpenP->PostNt31ReceiveHandler = TmpProtP->ProtocolCharacteristics.ReceiveHandler;
|
|
NewOpenP->PostNt31ReceiveCompleteHandler = TmpProtP->ProtocolCharacteristics.ReceiveCompleteHandler;
|
|
NewOpenP->ResetHandler = ndisMReset;
|
|
NewOpenP->ReceivePacketHandler =
|
|
(Miniport->DriverHandle->MiniportCharacteristics.ReturnPacketHandler == NULL) ?
|
|
NULL :
|
|
TmpProtP->ProtocolCharacteristics.ReceivePacketHandler;
|
|
|
|
//
|
|
// Save a pointer to the file object in the open...
|
|
//
|
|
NewOpenP->FileObject = FileObject;
|
|
|
|
//
|
|
// ...and a pointer to the open in the file object.
|
|
//
|
|
FileObject->FsContext = NewOpenP;
|
|
|
|
*NdisBindingHandle = (NDIS_HANDLE)NewOpenP;
|
|
|
|
//
|
|
// Insert the open into the filter package
|
|
//
|
|
switch (Miniport->MediaType)
|
|
{
|
|
case NdisMediumArcnet878_2:
|
|
|
|
if (!UsingEncapsulation)
|
|
{
|
|
FilterOpen = ArcNoteFilterOpenAdapter(Miniport->ArcDB,
|
|
MiniportOpen,
|
|
(NDIS_HANDLE)NewOpenP,
|
|
&MiniportOpen->FilterHandle);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If we're using ethernet encapsulation then
|
|
// we simply fall through to the ethernet stuff.
|
|
//
|
|
|
|
case NdisMedium802_3:
|
|
|
|
FilterOpen = EthNoteFilterOpenAdapter(Miniport->EthDB,
|
|
MiniportOpen,
|
|
(NDIS_HANDLE)NewOpenP,
|
|
&MiniportOpen->FilterHandle);
|
|
|
|
break;
|
|
|
|
case NdisMedium802_5:
|
|
|
|
FilterOpen = TrNoteFilterOpenAdapter(Miniport->TrDB,
|
|
MiniportOpen,
|
|
(NDIS_HANDLE)NewOpenP,
|
|
&MiniportOpen->FilterHandle);
|
|
|
|
break;
|
|
|
|
case NdisMediumFddi:
|
|
|
|
FilterOpen = FddiNoteFilterOpenAdapter(Miniport->FddiDB,
|
|
MiniportOpen,
|
|
(NDIS_HANDLE)NewOpenP,
|
|
&MiniportOpen->FilterHandle);
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
//
|
|
// Bogus non-NULL value
|
|
//
|
|
FilterOpen = 1;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Check for an open filter failure.
|
|
//
|
|
if (!FilterOpen)
|
|
{
|
|
//
|
|
// Something went wrong, clean up and exit.
|
|
//
|
|
*Status = NDIS_STATUS_OPEN_FAILED;
|
|
break;
|
|
}
|
|
|
|
ndisQueueOpenOnProtocol(NewOpenP, TmpProtP);
|
|
|
|
//
|
|
// Everything has been filled in. Synchronize access to the
|
|
// adapter block and link the new open adapter in.
|
|
//
|
|
MiniportOpen->MiniportNextOpen = Miniport->OpenQueue;
|
|
Miniport->OpenQueue = MiniportOpen;
|
|
|
|
//
|
|
// If this is the first open on the adapter then fire the
|
|
// wake-up-dpc timer.
|
|
//
|
|
if (NULL == MiniportOpen->MiniportNextOpen)
|
|
{
|
|
//
|
|
// Start wake up timer
|
|
//
|
|
NdisMSetPeriodicTimer((PNDIS_MINIPORT_TIMER)(&Miniport->WakeUpDpcTimer),
|
|
Miniport->CheckForHangTimeout);
|
|
}
|
|
|
|
*Status = NDIS_STATUS_SUCCESS;
|
|
} while (FALSE);
|
|
|
|
//
|
|
// Cleanup failure case
|
|
//
|
|
if (*Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
if (DerefMini)
|
|
{
|
|
ndisDereferenceMiniport(Miniport);
|
|
}
|
|
if (DerefProt)
|
|
{
|
|
ndisDereferenceProtocol(TmpProtP);
|
|
}
|
|
if (FreeOpen)
|
|
{
|
|
FREE_POOL(MiniportOpen);
|
|
}
|
|
ObDereferenceObject(FileObject);
|
|
FREE_POOL(NewOpenP);
|
|
}
|
|
}
|
|
|
|
NDIS_STATUS
|
|
ndisMFinishPendingOpen(
|
|
IN PMINIPORT_PENDING_OPEN MiniportPendingOpen
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handles any pending NdisOpenAdapter() calls for miniports.
|
|
|
|
NOTE: Must be called with spin lock held.
|
|
|
|
NOTE: Must be called with lock acquired flag set.
|
|
|
|
Arguments:
|
|
|
|
Miniport.
|
|
|
|
Return Value:
|
|
|
|
Returns the status code of the open.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Do the open again.
|
|
//
|
|
ndisMOpenAdapter(&MiniportPendingOpen->Status,
|
|
&MiniportPendingOpen->OpenErrorStatus,
|
|
MiniportPendingOpen->NdisBindingHandle,
|
|
MiniportPendingOpen->NdisProtocolHandle,
|
|
MiniportPendingOpen->ProtocolBindingContext,
|
|
MiniportPendingOpen->AdapterName,
|
|
MiniportPendingOpen->OpenOptions,
|
|
MiniportPendingOpen->AddressingInformation,
|
|
MiniportPendingOpen->Miniport,
|
|
MiniportPendingOpen->NewOpenP,
|
|
MiniportPendingOpen->FileObject,
|
|
(BOOLEAN)(MINIPORT_TEST_FLAG(MiniportPendingOpen,
|
|
fPENDING_OPEN_USING_ENCAPSULATION) ? TRUE : FALSE));
|
|
|
|
//
|
|
// If the open didn't pend then call the NdisCompleteOpenAdapter(),
|
|
//
|
|
if (MiniportPendingOpen->Status != NDIS_STATUS_PENDING)
|
|
{
|
|
//
|
|
// Complete the open to the protocol in a worker thread since we want this
|
|
// to happen at passive irql.
|
|
//
|
|
INITIALIZE_WORK_ITEM(&MiniportPendingOpen->WorkItem,
|
|
ndisMFinishQueuedPendingOpen,
|
|
MiniportPendingOpen);
|
|
QUEUE_WORK_ITEM(&MiniportPendingOpen->WorkItem, HyperCriticalWorkQueue);
|
|
}
|
|
|
|
return(MiniportPendingOpen->Status);
|
|
}
|
|
|
|
VOID
|
|
ndisMFinishQueuedPendingOpen(
|
|
IN PMINIPORT_PENDING_OPEN MiniportPendingOpen
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handles any pending NdisOpenAdapter() calls for miniports.
|
|
|
|
NOTE: Must be called with spin lock held.
|
|
|
|
NOTE: Must be called with lock acquired flag set.
|
|
|
|
Arguments:
|
|
|
|
Miniport.
|
|
|
|
Return Value:
|
|
|
|
Returns the status code of the open.
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_OPEN_BLOCK OpenP = MiniportPendingOpen->NewOpenP;
|
|
|
|
(OpenP->ProtocolHandle->ProtocolCharacteristics.OpenAdapterCompleteHandler) (
|
|
OpenP->ProtocolBindingContext,
|
|
MiniportPendingOpen->Status,
|
|
MiniportPendingOpen->OpenErrorStatus);
|
|
|
|
//
|
|
// We're done with this pending open context.
|
|
//
|
|
NdisFreeMemory(MiniportPendingOpen, sizeof(MINIPORT_PENDING_OPEN), 0);
|
|
}
|
|
|
|
//
|
|
// Io Port stuff
|
|
//
|
|
|
|
NDIS_STATUS
|
|
NdisMRegisterIoPortRange(
|
|
OUT PVOID * PortOffset,
|
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
|
IN UINT InitialPort,
|
|
IN UINT NumberOfPorts
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets up an IO port for operations.
|
|
|
|
Arguments:
|
|
|
|
PortOffset - The mapped port address the Miniport uses for NdisRaw functions.
|
|
|
|
MiniportAdapterHandle - Handle passed to Miniport Initialize.
|
|
|
|
InitialPort - Physical address of the starting port number.
|
|
|
|
NumberOfPorts - Number of ports to map.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle);
|
|
PHYSICAL_ADDRESS PortAddress;
|
|
PHYSICAL_ADDRESS InitialPortAddress;
|
|
ULONG addressSpace;
|
|
NDIS_STATUS Status;
|
|
|
|
CM_PARTIAL_RESOURCE_DESCRIPTOR Resource;
|
|
|
|
//
|
|
// First check if any bus access is allowed
|
|
//
|
|
if ((Miniport->BusType == (NDIS_INTERFACE_TYPE)-1) ||
|
|
(Miniport->BusNumber == (ULONG)-1))
|
|
{
|
|
return(NDIS_STATUS_FAILURE);
|
|
}
|
|
|
|
//
|
|
// Setup port
|
|
//
|
|
Resource.Type = CmResourceTypePort;
|
|
Resource.ShareDisposition = CmResourceShareDeviceExclusive;
|
|
Resource.Flags = (Miniport->AdapterType == NdisInterfaceInternal) ?
|
|
CM_RESOURCE_PORT_MEMORY : CM_RESOURCE_PORT_IO;
|
|
Resource.u.Port.Start.QuadPart = InitialPort;
|
|
Resource.u.Port.Length = NumberOfPorts;
|
|
|
|
//
|
|
// Add the new resource.
|
|
//
|
|
Status = ndisAddResource(
|
|
&Miniport->Resources,
|
|
&Resource,
|
|
Miniport->AdapterType,
|
|
Miniport->BusNumber,
|
|
Miniport->DriverHandle->NdisDriverInfo->NdisWrapperDriver,
|
|
Miniport->DeviceObject,
|
|
&Miniport->MiniportName);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Now Map the ports
|
|
//
|
|
|
|
//
|
|
// Get the system physical address for this card. The card uses
|
|
// I/O space, except for "internal" Jazz devices which use
|
|
// memory space.
|
|
//
|
|
addressSpace = (Miniport->AdapterType == NdisInterfaceInternal) ? 0 : 1;
|
|
|
|
InitialPortAddress.LowPart = InitialPort;
|
|
InitialPortAddress.HighPart = 0;
|
|
|
|
if (!HalTranslateBusAddress(Miniport->BusType, // InterfaceType
|
|
Miniport->BusNumber, // BusNumber
|
|
InitialPortAddress, // Bus Address
|
|
&addressSpace, // AddressSpace
|
|
&PortAddress)) // Translated address
|
|
{
|
|
//
|
|
// It would be nice to return a better status here, but we only get
|
|
// TRUE/FALSE back from HalTranslateBusAddress.
|
|
//
|
|
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
if (addressSpace == 0)
|
|
{
|
|
//
|
|
// memory space
|
|
//
|
|
|
|
*(PortOffset) = (PULONG)MmMapIoSpace(PortAddress,
|
|
NumberOfPorts,
|
|
FALSE);
|
|
|
|
if (*(PortOffset) == (PULONG)NULL)
|
|
{
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// I/O space
|
|
//
|
|
|
|
*(PortOffset) = (PULONG)PortAddress.LowPart;
|
|
}
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
VOID
|
|
NdisMDeregisterIoPortRange(
|
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
|
IN UINT InitialPort,
|
|
IN UINT NumberOfPorts,
|
|
IN PVOID PortOffset
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets up an IO port for operations.
|
|
|
|
Arguments:
|
|
|
|
MiniportAdapterHandle - Handle passed to Miniport Initialize.
|
|
|
|
InitialPort - Physical address of the starting port number.
|
|
|
|
NumberOfPorts - Number of ports to map.
|
|
|
|
PortOffset - The mapped port address the Miniport uses for NdisRaw functions.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle);
|
|
PHYSICAL_ADDRESS PortAddress;
|
|
PHYSICAL_ADDRESS InitialPortAddress;
|
|
ULONG addressSpace;
|
|
CM_PARTIAL_RESOURCE_DESCRIPTOR Resource;
|
|
NDIS_STATUS Status;
|
|
|
|
//
|
|
// Get the system physical address for this card. The card uses
|
|
// I/O space, except for "internal" Jazz devices which use
|
|
// memory space.
|
|
//
|
|
addressSpace = (Miniport->AdapterType == NdisInterfaceInternal) ? 0 : 1;
|
|
|
|
InitialPortAddress.LowPart = InitialPort;
|
|
InitialPortAddress.HighPart = 0;
|
|
|
|
HalTranslateBusAddress(Miniport->BusType, // InterfaceType
|
|
Miniport->BusNumber, // BusNumber
|
|
InitialPortAddress, // Bus Address
|
|
&addressSpace, // AddressSpace
|
|
&PortAddress); // Translated address
|
|
if (addressSpace == 0)
|
|
{
|
|
//
|
|
// memory space
|
|
//
|
|
MmUnmapIoSpace(PortOffset, NumberOfPorts);
|
|
}
|
|
|
|
//
|
|
// Build the resource to remove.
|
|
//
|
|
Resource.Type = CmResourceTypePort;
|
|
Resource.ShareDisposition = CmResourceShareDeviceExclusive;
|
|
Resource.Flags = (Miniport->AdapterType == NdisInterfaceInternal) ?
|
|
CM_RESOURCE_PORT_MEMORY : CM_RESOURCE_PORT_IO;
|
|
Resource.u.Port.Start.QuadPart = InitialPort;
|
|
Resource.u.Port.Length = NumberOfPorts;
|
|
|
|
//
|
|
// Remove the resource.
|
|
//
|
|
Status = ndisRemoveResource(
|
|
&Miniport->Resources,
|
|
&Resource,
|
|
Miniport->DriverHandle->NdisDriverInfo->NdisWrapperDriver,
|
|
Miniport->DeviceObject,
|
|
&Miniport->MiniportName);
|
|
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DBGPRINT(DBG_COMP_UNLOAD, DBG_LEVEL_INFO,
|
|
("NdisMDeregisterIoPortRange failed to remove the resource\n"));
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Attribute functions
|
|
//
|
|
|
|
VOID
|
|
NdisMSetAttributes(
|
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
|
IN NDIS_HANDLE MiniportAdapterContext,
|
|
IN BOOLEAN BusMaster,
|
|
IN NDIS_INTERFACE_TYPE AdapterType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function sets specific information about an adapter.
|
|
|
|
Arguments:
|
|
|
|
MiniportAdapterHandle - points to the adapter block.
|
|
|
|
MiniportAdapterContext - Context to pass to all Miniport driver functions.
|
|
|
|
BusMaster - TRUE if a bus mastering adapter.
|
|
|
|
AdapterType - Eisa, Isa, Mca or Internal.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
|
|
--*/
|
|
{
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
|
|
|
|
Miniport->MiniportAdapterContext = MiniportAdapterContext;
|
|
|
|
if (BusMaster)
|
|
MINIPORT_SET_FLAG(Miniport, fMINIPORT_BUS_MASTER);
|
|
|
|
Miniport->AdapterType = AdapterType;
|
|
|
|
MiniportReferencePackage();
|
|
if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO))
|
|
{
|
|
CoReferencePackage();
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NdisMSetAttributesEx(
|
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
|
IN NDIS_HANDLE MiniportAdapterContext,
|
|
IN UINT CheckForHangTimeInSeconds OPTIONAL,
|
|
IN ULONG AttributeFlags,
|
|
IN NDIS_INTERFACE_TYPE AdapterType OPTIONAL
|
|
)
|
|
{
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
|
|
|
|
Miniport->MiniportAdapterContext = MiniportAdapterContext;
|
|
|
|
Miniport->AdapterType = AdapterType;
|
|
|
|
//
|
|
// Set the new timeout value.
|
|
//
|
|
if (!ARGUMENT_PRESENT(CheckForHangTimeInSeconds))
|
|
{
|
|
CheckForHangTimeInSeconds = 2;
|
|
}
|
|
|
|
Miniport->CheckForHangTimeout = CheckForHangTimeInSeconds * 1000;
|
|
|
|
//
|
|
// Is this a bus master.
|
|
//
|
|
if (AttributeFlags & NDIS_ATTRIBUTE_BUS_MASTER)
|
|
{
|
|
MINIPORT_SET_FLAG(Miniport, fMINIPORT_BUS_MASTER);
|
|
}
|
|
|
|
//
|
|
// Should we ignore the packet queues?
|
|
//
|
|
if (AttributeFlags & NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT)
|
|
{
|
|
MINIPORT_SET_FLAG(Miniport, fMINIPORT_IGNORE_PACKET_QUEUE);
|
|
}
|
|
|
|
//
|
|
// Should we ignore the request queues?
|
|
//
|
|
if (AttributeFlags & NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT)
|
|
{
|
|
MINIPORT_SET_FLAG(Miniport, fMINIPORT_IGNORE_REQUEST_QUEUE);
|
|
}
|
|
|
|
//
|
|
// Should we ignore token ring errors?
|
|
//
|
|
if (AttributeFlags & NDIS_ATTRIBUTE_IGNORE_TOKEN_RING_ERRORS)
|
|
{
|
|
MINIPORT_SET_FLAG(Miniport, fMINIPORT_IGNORE_TOKEN_RING_ERRORS);
|
|
}
|
|
|
|
//
|
|
// Is this an intermediate miniport?
|
|
//
|
|
if (AttributeFlags & NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER)
|
|
{
|
|
MINIPORT_SET_FLAG(Miniport, fMINIPORT_INTERMEDIATE_DRIVER);
|
|
}
|
|
|
|
MiniportReferencePackage();
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
NdisMMapIoSpace(
|
|
OUT PVOID * VirtualAddress,
|
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
|
IN NDIS_PHYSICAL_ADDRESS PhysicalAddress,
|
|
IN UINT Length
|
|
)
|
|
{
|
|
NDIS_STATUS Status;
|
|
NdisMapIoSpace(&Status,
|
|
VirtualAddress,
|
|
MiniportAdapterHandle,
|
|
PhysicalAddress,
|
|
Length);
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
NdisMUnmapIoSpace(
|
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
|
IN PVOID VirtualAddress,
|
|
IN UINT Length
|
|
)
|
|
{
|
|
#ifndef _ALPHA_
|
|
MmUnmapIoSpace(VirtualAddress, Length);
|
|
#endif
|
|
}
|
|
|
|
|
|
VOID
|
|
NdisMAllocateSharedMemory(
|
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Cached,
|
|
OUT PVOID * VirtualAddress,
|
|
OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress
|
|
)
|
|
{
|
|
//
|
|
// Convert the handle to our internal structure.
|
|
//
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) MiniportAdapterHandle;
|
|
|
|
if (Miniport->SystemAdapterObject == NULL)
|
|
{
|
|
*VirtualAddress = NULL;
|
|
return;
|
|
}
|
|
|
|
NdisAllocateSharedMemory(MiniportAdapterHandle,
|
|
Length,
|
|
Cached,
|
|
VirtualAddress,
|
|
PhysicalAddress);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
NdisMAllocateSharedMemoryAsync(
|
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Cached,
|
|
IN PVOID Context
|
|
)
|
|
{
|
|
//
|
|
// Convert the handle to our internal structure.
|
|
//
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) MiniportAdapterHandle;
|
|
PASYNC_WORKITEM pWorkItem = NULL;
|
|
|
|
// Allocate a workitem
|
|
if ((Miniport->SystemAdapterObject != NULL) &&
|
|
(Miniport->DriverHandle->MiniportCharacteristics.AllocateCompleteHandler != NULL))
|
|
{
|
|
NdisAllocateMemory(&pWorkItem,
|
|
sizeof(ASYNC_WORKITEM),
|
|
0,
|
|
HighestAcceptableMax);
|
|
}
|
|
|
|
if ((pWorkItem == NULL) ||
|
|
!ndisReferenceMiniport(Miniport))
|
|
{
|
|
if (pWorkItem != NULL)
|
|
NdisFreeMemory(pWorkItem, sizeof(ASYNC_WORKITEM), 0);
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
// Initialize the workitem and queue it up to a worker thread
|
|
pWorkItem->Miniport = Miniport;
|
|
pWorkItem->Length = Length;
|
|
pWorkItem->Cached = Cached;
|
|
pWorkItem->Context = Context;
|
|
INITIALIZE_WORK_ITEM(&pWorkItem->ExWorkItem, ndisMQueuedAllocateSharedHandler, pWorkItem);
|
|
QUEUE_WORK_ITEM(&pWorkItem->ExWorkItem, CriticalWorkQueue);
|
|
|
|
return NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
|
|
VOID
|
|
ndisMQueuedAllocateSharedHandler(
|
|
IN PASYNC_WORKITEM pWorkItem
|
|
)
|
|
{
|
|
KIRQL OldIrql;
|
|
|
|
// Allocate the memory
|
|
NdisMAllocateSharedMemory(pWorkItem->Miniport,
|
|
pWorkItem->Length,
|
|
pWorkItem->Cached,
|
|
&pWorkItem->VAddr,
|
|
&pWorkItem->PhyAddr);
|
|
|
|
if (pWorkItem->Miniport->Flags & fMINIPORT_IS_CO)
|
|
{
|
|
NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(pWorkItem->Miniport, &OldIrql);
|
|
}
|
|
else
|
|
{
|
|
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
|
}
|
|
|
|
// Call the miniport back
|
|
(*pWorkItem->Miniport->DriverHandle->MiniportCharacteristics.AllocateCompleteHandler)(
|
|
pWorkItem->Miniport->MiniportAdapterContext,
|
|
pWorkItem->VAddr,
|
|
&pWorkItem->PhyAddr,
|
|
pWorkItem->Length,
|
|
pWorkItem->Context);
|
|
|
|
if (pWorkItem->Miniport->Flags & fMINIPORT_IS_CO)
|
|
{
|
|
NDIS_RELEASE_MINIPORT_SPIN_LOCK(pWorkItem->Miniport, OldIrql);
|
|
}
|
|
else
|
|
{
|
|
KeLowerIrql(OldIrql);
|
|
}
|
|
|
|
// Dereference the miniport
|
|
ndisDereferenceMiniport(pWorkItem->Miniport);
|
|
|
|
// And finally free the work-item
|
|
NdisFreeMemory(pWorkItem, sizeof(ASYNC_WORKITEM), 0);
|
|
}
|
|
|
|
VOID
|
|
NdisMFreeSharedMemory(
|
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
|
IN ULONG Length,
|
|
IN BOOLEAN Cached,
|
|
IN PVOID VirtualAddress,
|
|
IN NDIS_PHYSICAL_ADDRESS PhysicalAddress
|
|
)
|
|
{
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
|
|
|
|
if (CURRENT_IRQL < DISPATCH_LEVEL)
|
|
{
|
|
NdisFreeSharedMemory(MiniportAdapterHandle,
|
|
Length,
|
|
Cached,
|
|
VirtualAddress,
|
|
PhysicalAddress);
|
|
}
|
|
else if (ndisReferenceMiniport(Miniport))
|
|
{
|
|
PASYNC_WORKITEM pWorkItem = NULL;
|
|
|
|
// Allocate a work-item and queue it up to a worker thread
|
|
NdisAllocateMemory(&pWorkItem,
|
|
sizeof(ASYNC_WORKITEM),
|
|
0,
|
|
HighestAcceptableMax);
|
|
|
|
if (pWorkItem != NULL)
|
|
{
|
|
// Initialize the workitem and queue it up to a worker thread
|
|
pWorkItem->Miniport = Miniport;
|
|
pWorkItem->Length = Length;
|
|
pWorkItem->Cached = Cached;
|
|
pWorkItem->VAddr = VirtualAddress;
|
|
pWorkItem->PhyAddr = PhysicalAddress;
|
|
INITIALIZE_WORK_ITEM(&pWorkItem->ExWorkItem, ndisMQueuedFreeSharedHandler, pWorkItem);
|
|
QUEUE_WORK_ITEM(&pWorkItem->ExWorkItem, CriticalWorkQueue);
|
|
}
|
|
|
|
// What do we do now ?
|
|
}
|
|
}
|
|
|
|
VOID
|
|
ndisMQueuedFreeSharedHandler(
|
|
IN PASYNC_WORKITEM pWorkItem
|
|
)
|
|
{
|
|
// Free the memory
|
|
NdisFreeSharedMemory(pWorkItem->Miniport,
|
|
pWorkItem->Length,
|
|
pWorkItem->Cached,
|
|
pWorkItem->VAddr,
|
|
pWorkItem->PhyAddr);
|
|
|
|
// Dereference the miniport
|
|
ndisDereferenceMiniport(pWorkItem->Miniport);
|
|
|
|
// And finally free the work-item
|
|
NdisFreeMemory(pWorkItem, sizeof(ASYNC_WORKITEM), 0);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
NdisMRegisterDmaChannel(
|
|
OUT PNDIS_HANDLE MiniportDmaHandle,
|
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
|
IN UINT DmaChannel,
|
|
IN BOOLEAN Dma32BitAddresses,
|
|
IN PNDIS_DMA_DESCRIPTION DmaDescription,
|
|
IN ULONG MaximumLength
|
|
)
|
|
{
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle);
|
|
NDIS_STATUS Status;
|
|
Miniport->ChannelNumber = (DmaChannel);
|
|
|
|
if (Dma32BitAddresses)
|
|
MINIPORT_SET_FLAG(Miniport, fMINIPORT_DMA_32_BIT_ADDRESSES);
|
|
|
|
NdisAllocateDmaChannel(&Status,
|
|
MiniportDmaHandle,
|
|
(NDIS_HANDLE)Miniport,
|
|
DmaDescription,
|
|
MaximumLength);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
NdisMDeregisterDmaChannel(
|
|
IN NDIS_HANDLE MiniportDmaHandle
|
|
)
|
|
{
|
|
NdisFreeDmaChannel(MiniportDmaHandle);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
NdisMAllocateMapRegisters(
|
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
|
IN UINT DmaChannel,
|
|
IN BOOLEAN Dma32BitAddresses,
|
|
IN ULONG PhysicalMapRegistersNeeded,
|
|
IN ULONG MaximumPhysicalMapping
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocates map registers for bus mastering devices.
|
|
|
|
Arguments:
|
|
|
|
MiniportAdapterHandle - Handle passed to MiniportInitialize.
|
|
|
|
PhysicalMapRegistersNeeded - The maximum number of map registers needed
|
|
by the Miniport at any one time.
|
|
|
|
MaximumPhysicalMapping - Maximum length of a buffer that will have to be mapped.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Convert the handle to our internal structure.
|
|
//
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) MiniportAdapterHandle;
|
|
|
|
//
|
|
// This is needed by HalGetAdapter.
|
|
//
|
|
DEVICE_DESCRIPTION DeviceDescription;
|
|
|
|
//
|
|
// Returned by HalGetAdapter.
|
|
//
|
|
ULONG MapRegistersAllowed;
|
|
|
|
//
|
|
// Returned by HalGetAdapter.
|
|
//
|
|
PADAPTER_OBJECT AdapterObject;
|
|
|
|
//
|
|
// Map registers needed per channel.
|
|
//
|
|
ULONG MapRegistersPerChannel;
|
|
|
|
NTSTATUS NtStatus;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
UINT i;
|
|
|
|
LARGE_INTEGER TimeoutValue;
|
|
|
|
//
|
|
// If the device is a busmaster, we get an adapter
|
|
// object for it.
|
|
// If map registers are needed, we loop, allocating an
|
|
// adapter channel for each map register needed.
|
|
//
|
|
|
|
if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_BUS_MASTER) &&
|
|
(Miniport->BusType != (NDIS_INTERFACE_TYPE)-1) &&
|
|
(Miniport->BusNumber != (ULONG)-1))
|
|
{
|
|
TimeoutValue.QuadPart = Int32x32To64(2 * 1000, -10000);
|
|
|
|
Miniport->PhysicalMapRegistersNeeded = PhysicalMapRegistersNeeded;
|
|
Miniport->MaximumPhysicalMapping = MaximumPhysicalMapping;
|
|
|
|
//
|
|
// Allocate storage for holding the appropriate
|
|
// information for each map register.
|
|
//
|
|
|
|
Miniport->MapRegisters = (PMAP_REGISTER_ENTRY)
|
|
ALLOC_FROM_POOL(sizeof(MAP_REGISTER_ENTRY) * PhysicalMapRegistersNeeded,
|
|
NDIS_TAG_DEFAULT);
|
|
|
|
if (Miniport->MapRegisters == (PMAP_REGISTER_ENTRY)NULL)
|
|
{
|
|
//
|
|
// Error out
|
|
//
|
|
|
|
NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport,
|
|
NDIS_ERROR_CODE_OUT_OF_RESOURCES,
|
|
1,
|
|
0xFFFFFFFF);
|
|
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Use this event to tell us when ndisAllocationExecutionRoutine
|
|
// has been called.
|
|
//
|
|
|
|
INITIALIZE_EVENT(&Miniport->AllocationEvent);
|
|
|
|
//
|
|
// Set up the device description; zero it out in case its
|
|
// size changes.
|
|
//
|
|
|
|
ZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
|
|
|
|
DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
|
|
DeviceDescription.Master = TRUE;
|
|
DeviceDescription.ScatterGather = TRUE;
|
|
|
|
DeviceDescription.BusNumber = Miniport->BusNumber;
|
|
DeviceDescription.DmaChannel = DmaChannel;
|
|
DeviceDescription.InterfaceType = Miniport->AdapterType;
|
|
|
|
if (DeviceDescription.InterfaceType == NdisInterfaceIsa)
|
|
{
|
|
//
|
|
// For ISA devices, the width is based on the DMA channel:
|
|
// 0-3 == 8 bits, 5-7 == 16 bits. Timing is compatibility
|
|
// mode.
|
|
//
|
|
|
|
if (DmaChannel > 4)
|
|
{
|
|
DeviceDescription.DmaWidth = Width16Bits;
|
|
}
|
|
else
|
|
{
|
|
DeviceDescription.DmaWidth = Width8Bits;
|
|
}
|
|
DeviceDescription.DmaSpeed = Compatible;
|
|
|
|
}
|
|
else if ((DeviceDescription.InterfaceType == NdisInterfaceEisa) ||
|
|
(DeviceDescription.InterfaceType == NdisInterfacePci) ||
|
|
(DeviceDescription.InterfaceType == NdisInterfaceMca))
|
|
{
|
|
DeviceDescription.Dma32BitAddresses = Dma32BitAddresses;
|
|
}
|
|
|
|
DeviceDescription.MaximumLength = MaximumPhysicalMapping;
|
|
|
|
//
|
|
// Get the adapter object.
|
|
//
|
|
|
|
AdapterObject = HalGetAdapter (&DeviceDescription, &MapRegistersAllowed);
|
|
|
|
if (AdapterObject == NULL)
|
|
{
|
|
NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport,
|
|
NDIS_ERROR_CODE_OUT_OF_RESOURCES,
|
|
1,
|
|
0xFFFFFFFF);
|
|
|
|
FREE_POOL(Miniport->MapRegisters);
|
|
Miniport->MapRegisters = NULL;
|
|
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
|
|
("<==NdisRegisterAdapter\n"));
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// We save this to call IoFreeMapRegisters later.
|
|
//
|
|
|
|
Miniport->SystemAdapterObject = AdapterObject;
|
|
|
|
//
|
|
// Determine how many map registers we need per channel.
|
|
//
|
|
|
|
MapRegistersPerChannel = ((MaximumPhysicalMapping - 2) / PAGE_SIZE) + 2;
|
|
|
|
ASSERT (MapRegistersAllowed >= MapRegistersPerChannel);
|
|
|
|
//
|
|
// Now loop, allocating an adapter channel each time, then
|
|
// freeing everything but the map registers.
|
|
//
|
|
|
|
for (i=0; i<Miniport->PhysicalMapRegistersNeeded; i++)
|
|
{
|
|
Miniport->CurrentMapRegister = i;
|
|
|
|
RAISE_IRQL_TO_DISPATCH(&OldIrql);
|
|
|
|
NtStatus = IoAllocateAdapterChannel(AdapterObject,
|
|
Miniport->DeviceObject,
|
|
MapRegistersPerChannel,
|
|
ndisAllocationExecutionRoutine,
|
|
Miniport);
|
|
|
|
if (!NT_SUCCESS(NtStatus))
|
|
{
|
|
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
|
|
("AllocateAdapterChannel: %lx\n", NtStatus));
|
|
|
|
for (; i != 0; i--)
|
|
{
|
|
IoFreeMapRegisters(Miniport->SystemAdapterObject,
|
|
Miniport->MapRegisters[i-1].MapRegister,
|
|
MapRegistersPerChannel);
|
|
}
|
|
|
|
LOWER_IRQL(OldIrql);
|
|
|
|
NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport,
|
|
NDIS_ERROR_CODE_OUT_OF_RESOURCES,
|
|
1,
|
|
0xFFFFFFFF);
|
|
|
|
FREE_POOL(Miniport->MapRegisters);
|
|
Miniport->MapRegisters = NULL;
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
LOWER_IRQL(OldIrql);
|
|
|
|
TimeoutValue.QuadPart = Int32x32To64(2 * 1000, -10000);
|
|
|
|
//
|
|
// ndisAllocationExecutionRoutine will set this event
|
|
// when it has gotten FirstTranslationEntry.
|
|
//
|
|
|
|
NtStatus = WAIT_FOR_OBJECT(&Miniport->AllocationEvent, &TimeoutValue);
|
|
|
|
if (NtStatus != STATUS_SUCCESS)
|
|
{
|
|
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
|
|
("NDIS DMA AllocateAdapterChannel: %lx\n", NtStatus));
|
|
|
|
RAISE_IRQL_TO_DISPATCH(&OldIrql);
|
|
|
|
for (; i != 0; i--)
|
|
{
|
|
IoFreeMapRegisters(Miniport->SystemAdapterObject,
|
|
Miniport->MapRegisters[i-1].MapRegister,
|
|
MapRegistersPerChannel);
|
|
}
|
|
|
|
LOWER_IRQL(OldIrql);
|
|
|
|
NdisWriteErrorLogEntry((NDIS_HANDLE)Miniport,
|
|
NDIS_ERROR_CODE_OUT_OF_RESOURCES,
|
|
1,
|
|
0xFFFFFFFF);
|
|
|
|
FREE_POOL(Miniport->MapRegisters);
|
|
Miniport->MapRegisters = NULL;
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
RESET_EVENT(&Miniport->AllocationEvent);
|
|
}
|
|
}
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
VOID
|
|
NdisMFreeMapRegisters(
|
|
IN NDIS_HANDLE MiniportAdapterHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Releases allocated map registers
|
|
|
|
Arguments:
|
|
|
|
MiniportAdapterHandle - Handle passed to MiniportInitialize.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Convert the handle to our internal structure.
|
|
//
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) MiniportAdapterHandle;
|
|
|
|
KIRQL OldIrql;
|
|
|
|
ULONG i;
|
|
|
|
if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_BUS_MASTER) &&
|
|
(Miniport->MapRegisters != NULL)
|
|
)
|
|
{
|
|
ULONG MapRegistersPerChannel =
|
|
((Miniport->MaximumPhysicalMapping - 2) / PAGE_SIZE) + 2;
|
|
|
|
for (i=0; i<Miniport->PhysicalMapRegistersNeeded; i++)
|
|
{
|
|
RAISE_IRQL_TO_DISPATCH(&OldIrql);
|
|
|
|
IoFreeMapRegisters(Miniport->SystemAdapterObject,
|
|
Miniport->MapRegisters[i].MapRegister,
|
|
MapRegistersPerChannel);
|
|
|
|
LOWER_IRQL(OldIrql);
|
|
}
|
|
|
|
FREE_POOL(Miniport->MapRegisters);
|
|
|
|
Miniport->MapRegisters = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
NdisMReadDmaCounter(
|
|
IN NDIS_HANDLE MiniportDmaHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads the current value of the dma counter
|
|
|
|
Arguments:
|
|
|
|
MiniportDmaHandle - Handle for the DMA transfer.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
return HalReadDmaCounter(((PNDIS_DMA_BLOCK)(MiniportDmaHandle))->SystemAdapterObject);
|
|
}
|
|
|
|
|
|
VOID
|
|
ndisBugcheckHandler(
|
|
IN PNDIS_WRAPPER_CONTEXT WrapperContext,
|
|
IN ULONG Size
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called when a bugcheck occurs in the system.
|
|
|
|
Arguments:
|
|
|
|
Buffer -- Ndis wrapper context.
|
|
|
|
Size -- Size of wrapper context
|
|
|
|
Return Value:
|
|
|
|
Void.
|
|
|
|
--*/
|
|
{
|
|
if (Size == sizeof(NDIS_WRAPPER_CONTEXT))
|
|
{
|
|
if (WrapperContext->ShutdownHandler != NULL)
|
|
{
|
|
WrapperContext->ShutdownHandler(WrapperContext->ShutdownContext);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
NdisMRegisterAdapterShutdownHandler(
|
|
IN NDIS_HANDLE MiniportHandle,
|
|
IN PVOID ShutdownContext,
|
|
IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deregisters an NDIS adapter.
|
|
|
|
Arguments:
|
|
|
|
MiniportHandle - The miniport.
|
|
|
|
ShutdownHandler - The Handler for the Adapter, to be called on shutdown.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
{
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) MiniportHandle;
|
|
PNDIS_WRAPPER_CONTEXT WrapperContext = Miniport->WrapperContext;
|
|
|
|
if (WrapperContext->ShutdownHandler == NULL)
|
|
{
|
|
//
|
|
// Store information
|
|
//
|
|
|
|
WrapperContext->ShutdownHandler = ShutdownHandler;
|
|
WrapperContext->ShutdownContext = ShutdownContext;
|
|
|
|
//
|
|
// Register our shutdown handler for a bugcheck. (Note that we are
|
|
// already registered for shutdown notification.)
|
|
//
|
|
|
|
KeInitializeCallbackRecord(&WrapperContext->BugcheckCallbackRecord);
|
|
|
|
KeRegisterBugCheckCallback(&WrapperContext->BugcheckCallbackRecord, // callback record.
|
|
ndisBugcheckHandler, // callback routine.
|
|
WrapperContext, // free form buffer.
|
|
sizeof(NDIS_WRAPPER_CONTEXT), // buffer size.
|
|
"Ndis miniport"); // component id.
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
NdisMDeregisterAdapterShutdownHandler(
|
|
IN NDIS_HANDLE MiniportHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
MiniportHandle - The miniport.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) MiniportHandle;
|
|
PNDIS_WRAPPER_CONTEXT WrapperContext = Miniport->WrapperContext;
|
|
|
|
//
|
|
// Clear information
|
|
//
|
|
|
|
if (WrapperContext->ShutdownHandler != NULL)
|
|
{
|
|
KeDeregisterBugCheckCallback(&WrapperContext->BugcheckCallbackRecord);
|
|
WrapperContext->ShutdownHandler = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
NdisMPciAssignResources(
|
|
IN NDIS_HANDLE MiniportHandle,
|
|
IN ULONG SlotNumber,
|
|
OUT PNDIS_RESOURCE_LIST * AssignedResources
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine uses the Hal to assign a set of resources to a PCI
|
|
device.
|
|
|
|
Arguments:
|
|
|
|
MiniportHandle - The miniport.
|
|
|
|
SlotNumber - Slot number of the device.
|
|
|
|
AssignedResources - The returned resources.
|
|
|
|
Return Value:
|
|
|
|
Status of the operation
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NtStatus;
|
|
PCM_RESOURCE_LIST AllocatedResources = NULL;
|
|
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) MiniportHandle;
|
|
|
|
NtStatus = HalAssignSlotResources ((PUNICODE_STRING)(Miniport->DriverHandle->NdisDriverInfo->NdisWrapperConfigurationHandle),
|
|
NULL,
|
|
Miniport->DriverHandle->NdisDriverInfo->NdisWrapperDriver,
|
|
Miniport->DeviceObject,
|
|
Miniport->BusType,
|
|
Miniport->BusNumber,
|
|
SlotNumber,
|
|
&AllocatedResources);
|
|
|
|
if (NtStatus != STATUS_SUCCESS)
|
|
{
|
|
*AssignedResources = NULL;
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
//
|
|
// Store resources into the driver wide block
|
|
//
|
|
((PNDIS_WRAPPER_CONTEXT)Miniport->WrapperContext)->AssignedSlotResources = AllocatedResources;
|
|
|
|
*AssignedResources = &(AllocatedResources->List[0].PartialResourceList);
|
|
|
|
//
|
|
// Update slot number since the driver can also scan and so the one
|
|
// in the registry is probably invalid
|
|
//
|
|
Miniport->SlotNumber = SlotNumber;
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
NdisMQueryAdapterResources(
|
|
OUT PNDIS_STATUS Status,
|
|
IN NDIS_HANDLE WrapperConfigurationContext,
|
|
OUT PNDIS_RESOURCE_LIST ResourceList,
|
|
IN IN PUINT BufferSize
|
|
)
|
|
{
|
|
*Status = NDIS_STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
|
|
|