Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

2788 lines
68 KiB

/*++
Copyright (c) 1990-1995 Microsoft Corporation
Module Name:
config.c
Abstract:
NDIS wrapper functions for full mac drivers configuration/initialization
Author:
Sean Selitrennikoff (SeanSe) 05-Oct-93
Jameel Hyder (JameelH) 01-Jun-95 Re-organization/optimization
Environment:
Kernel mode, FSD
Revision History:
--*/
#include <precomp.h>
#pragma hdrstop
#include <stdarg.h>
//
// Define the module number for debug code.
//
#define MODULE_NUMBER MODULE_CONFIG
//
// Requests Used by MAC Drivers
//
//
VOID
NdisInitializeWrapper(
OUT PNDIS_HANDLE NdisWrapperHandle,
IN PVOID SystemSpecific1,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3
)
/*++
Routine Description:
Called at the beginning of every MAC's initialization routine.
Arguments:
NdisWrapperHandle - A MAC specific handle for the wrapper.
SystemSpecific1, a pointer to the driver object for the MAC.
SystemSpecific2, a PUNICODE_STRING containing the location of
the registry subtree for this driver.
SystemSpecific3, unused on NT.
Return Value:
None.
--*/
{
NDIS_STATUS Status;
PUNICODE_STRING RegPath;
PNDIS_WRAPPER_HANDLE WrapperHandle;
UNREFERENCED_PARAMETER (SystemSpecific3);
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("==>NdisInitializeWrapper\n"));
*NdisWrapperHandle = NULL;
Status = NdisAllocateMemory((PVOID*)NdisWrapperHandle,
sizeof(NDIS_WRAPPER_HANDLE) +
sizeof(UNICODE_STRING) +
((PUNICODE_STRING)SystemSpecific2)->Length +
sizeof(WCHAR),
0,
HighestAcceptableMax);
if (Status == NDIS_STATUS_SUCCESS)
{
WrapperHandle = (PNDIS_WRAPPER_HANDLE)(*NdisWrapperHandle);
WrapperHandle->NdisWrapperDriver = (PDRIVER_OBJECT)SystemSpecific1;
RegPath = (PUNICODE_STRING)((PUCHAR)WrapperHandle + sizeof(NDIS_WRAPPER_HANDLE));
RegPath->Buffer = (PWSTR)((PUCHAR)RegPath + sizeof(UNICODE_STRING));
RegPath->MaximumLength =
RegPath->Length = ((PUNICODE_STRING)SystemSpecific2)->Length;
NdisMoveMemory(RegPath->Buffer,
((PUNICODE_STRING)SystemSpecific2)->Buffer,
RegPath->Length);
WrapperHandle->NdisWrapperConfigurationHandle = RegPath;
}
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("<==NdisInitializeWrapper\n"));
}
VOID
NdisTerminateWrapper(
IN NDIS_HANDLE NdisWrapperHandle,
IN PVOID SystemSpecific
)
/*++
Routine Description:
Called at the end of every MAC's termination routine.
Arguments:
NdisWrapperHandle - The handle returned from NdisInitializeWrapper.
SystemSpecific - No defined value.
Return Value:
None.
--*/
{
PNDIS_WRAPPER_HANDLE NdisMacInfo = (PNDIS_WRAPPER_HANDLE)NdisWrapperHandle;
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("==>NdisTerminateWrapper\n"));
UNREFERENCED_PARAMETER(SystemSpecific);
if (NdisMacInfo != NULL)
{
NdisFreeMemory(NdisMacInfo, sizeof(NDIS_WRAPPER_HANDLE), 0);
}
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("<==NdisTerminateWrapper\n"));
}
//
// Operating System Requests
//
//
VOID
NdisMapIoSpace(
OUT PNDIS_STATUS Status,
OUT PVOID * VirtualAddress,
IN NDIS_HANDLE NdisAdapterHandle,
IN NDIS_PHYSICAL_ADDRESS PhysicalAddress,
IN UINT Length
)
/*++
Routine Description:
Map virtual memory address space onto a physical address.
Arguments:
Status - resulting status
VirtualAddress - resulting address in virtual space.
NdisAdapterHandle - value returned by NdisRegisterAdapter.
PhysicalAddress - Physical address.
Length - Size of requested memory mapping
Return Value:
none.
--*/
{
ULONG addressSpace = 0;
ULONG NumberOfElements;
ULONG BusNumber;
NDIS_INTERFACE_TYPE BusType;
PHYSICAL_ADDRESS PhysicalTemp;
PCM_RESOURCE_LIST Resources, Resc;
BOOLEAN Conflict;
NTSTATUS NtStatus;
PNDIS_ADAPTER_BLOCK AdptrP = (PNDIS_ADAPTER_BLOCK)(NdisAdapterHandle);
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)(NdisAdapterHandle);
//
// First check if any bus access is allowed
//
BusType = (AdptrP->DeviceObject != NULL) ? AdptrP->BusType : Miniport->BusType;
BusNumber = (AdptrP->DeviceObject != NULL) ? AdptrP->BusNumber : Miniport->BusNumber;
do
{
if ((BusType == (NDIS_INTERFACE_TYPE)-1) || (BusNumber == (ULONG)-1))
{
*Status = NDIS_STATUS_FAILURE;
break;
}
//
// First check for resource conflict by expanding current resource list,
// adding in the mapped space, and then re-submitting the resource list.
//
Resc = (AdptrP->DeviceObject != NULL) ? AdptrP->Resources : Miniport->Resources;
if (Resc != NULL)
{
NumberOfElements = Resc->List[0].PartialResourceList.Count + 1;
}
else
{
NumberOfElements = 1;
}
//
// First check for resource conflict by expanding current resource list,
// adding in the mapped space, and then re-submitting the resource list.
//
Resources = (PCM_RESOURCE_LIST)ALLOC_FROM_POOL(sizeof(CM_RESOURCE_LIST) +
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) *
NumberOfElements,
NDIS_TAG_RSRC_LIST);
if (Resources == NULL)
{
*Status = NDIS_STATUS_RESOURCES;
break;
}
if (Resc != NULL)
{
CopyMemory(Resources,
Resc,
sizeof(CM_RESOURCE_LIST) +
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) *
(NumberOfElements-1));
}
else
{
//
// Setup initial resource info -- NOTE: This is definitely a mini-port
//
ASSERT(AdptrP->DeviceObject == NULL);
Resources->Count = 1;
Resources->List[0].InterfaceType = Miniport->AdapterType;
Resources->List[0].BusNumber = BusNumber;
Resources->List[0].PartialResourceList.Version = 0;
Resources->List[0].PartialResourceList.Revision = 0;
Resources->List[0].PartialResourceList.Count = 0;
}
//
// Setup memory
//
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].Type =
CmResourceTypeMemory;
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].ShareDisposition =
CmResourceShareDeviceExclusive;
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].Flags =
CM_RESOURCE_MEMORY_READ_WRITE;
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].u.Memory.Start =
PhysicalAddress;
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].u.Memory.Length =
Length;
Resources->List[0].PartialResourceList.Count++;
//
// Make the call
//
NtStatus = IoReportResourceUsage(NULL,
((AdptrP->DeviceObject != NULL) ?
AdptrP->MacHandle->NdisMacInfo->NdisWrapperDriver :
Miniport->DriverHandle->NdisDriverInfo->NdisWrapperDriver),
NULL,
0,
(AdptrP->DeviceObject != NULL) ?
AdptrP->DeviceObject:
Miniport->DeviceObject,
Resources,
sizeof(CM_RESOURCE_LIST) +
(sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)*Resources->List[0].PartialResourceList.Count),
TRUE,
&Conflict);
//
// Check for conflict.
//
if (Resc != NULL)
{
FREE_POOL(Resc);
}
if (AdptrP->DeviceObject != NULL)
{
AdptrP->Resources = Resources;
}
else
{
Miniport->Resources = Resources;
}
if (Conflict || (NtStatus != STATUS_SUCCESS))
{
if (Conflict)
{
//
// Log an error
//
PIO_ERROR_LOG_PACKET errorLogEntry;
volatile ULONG i;
ULONG StringSize;
PUCHAR Place;
PWCH baseFileName;
WCHAR Character;
ULONG Value;
baseFileName = ((AdptrP->DeviceObject != NULL) ?
AdptrP->AdapterName.Buffer :
Miniport->MiniportName.Buffer);
//
// Parse out the path name, leaving only the device name.
//
for (i = 0;
i < ((AdptrP->DeviceObject != NULL) ?
AdptrP->AdapterName.Length :
Miniport->MiniportName.Length) / sizeof(WCHAR);
i++)
{
//
// If s points to a directory separator, set baseFileName to
// the character after the separator.
//
if (((AdptrP->DeviceObject != NULL) ?
AdptrP->AdapterName.Buffer[i] :
Miniport->MiniportName.Buffer[i]) == OBJ_NAME_PATH_SEPARATOR)
{
baseFileName = ((AdptrP->DeviceObject != NULL) ?
&(AdptrP->AdapterName.Buffer[++i]):
&(Miniport->MiniportName.Buffer[++i]));
}
}
StringSize = ((AdptrP->DeviceObject != NULL) ?
AdptrP->AdapterName.MaximumLength :
Miniport->MiniportName.MaximumLength) -
(((ULONG)baseFileName) -
((AdptrP->DeviceObject != NULL) ?
((ULONG)AdptrP->AdapterName.Buffer) :
((ULONG)Miniport->MiniportName.Buffer)));
errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(((AdptrP->DeviceObject != NULL) ?
AdptrP->DeviceObject : Miniport->DeviceObject),
(UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + StringSize + 34));
// wstrlen("FFFFFFFFFFFFFFFF") * sizeof(WHCAR) + sizeof(UNICODE_NULL)
if (errorLogEntry != NULL)
{
errorLogEntry->ErrorCode = EVENT_NDIS_MEMORY_CONFLICT;
//
// store the time
//
errorLogEntry->MajorFunctionCode = 0;
errorLogEntry->RetryCount = 0;
errorLogEntry->UniqueErrorValue = 0;
errorLogEntry->FinalStatus = 0;
errorLogEntry->SequenceNumber = 0;
errorLogEntry->IoControlCode = 0;
//
// Set string information
//
if (StringSize != 0)
{
errorLogEntry->NumberOfStrings = 1;
errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET);
CopyMemory (((PUCHAR)errorLogEntry) + sizeof(IO_ERROR_LOG_PACKET),
(PVOID)baseFileName,
StringSize);
Place = ((PUCHAR)errorLogEntry) +
sizeof(IO_ERROR_LOG_PACKET) +
StringSize;
}
else
{
Place = ((PUCHAR)errorLogEntry) +
sizeof(IO_ERROR_LOG_PACKET);
errorLogEntry->NumberOfStrings = 0;
}
errorLogEntry->NumberOfStrings++;
//
// Put in memory address
//
for (StringSize = 0; StringSize < 2; StringSize++)
{
if (StringSize == 0)
{
//
// Do high part
//
Value = NdisGetPhysicalAddressHigh(PhysicalAddress);
}
else
{
//
// Do Low part
//
Value = NdisGetPhysicalAddressLow(PhysicalAddress);
}
//
// Convert value
//
for (i = 1; i <= (sizeof(ULONG) * 2); i++)
{
WCHAR c;
c = (WCHAR)((Value >> (((sizeof(ULONG) * 2) - i) * 4)) & 0x0F);
if (c <= 9)
{
Character = L'0' + c;
}
else
{
Character = L'A' + c - 10;
}
memcpy((PVOID)Place, (PVOID)&Character, sizeof(WCHAR));
Place += sizeof(WCHAR);
}
}
Character = UNICODE_NULL;
memcpy((PVOID)Place, (PVOID)&Character, sizeof(WCHAR));
//
// write it out
//
IoWriteErrorLogEntry(errorLogEntry);
}
*Status = NDIS_STATUS_RESOURCE_CONFLICT;
break;
}
*Status = NDIS_STATUS_FAILURE;
break;
}
if (!HalTranslateBusAddress(BusType,
BusNumber,
PhysicalAddress,
&addressSpace,
&PhysicalTemp))
{
//
// It would be nice to return a better status here, but we only get
// TRUE/FALSE back from HalTranslateBusAddress.
//
*Status = NDIS_STATUS_FAILURE;
break;
}
if (addressSpace == 0)
{
//
// memory space
//
*VirtualAddress = MmMapIoSpace(PhysicalTemp, (Length), FALSE);
}
else
{
//
// I/O space
//
*VirtualAddress = (PVOID)(PhysicalTemp.LowPart);
}
*Status = NDIS_STATUS_SUCCESS;
if (*VirtualAddress == NULL)
{
*Status = NDIS_STATUS_RESOURCES;
}
} while (FALSE);
}
VOID
NdisAllocateDmaChannel(
OUT PNDIS_STATUS Status,
OUT PNDIS_HANDLE NdisDmaHandle,
IN NDIS_HANDLE NdisAdapterHandle,
IN PNDIS_DMA_DESCRIPTION DmaDescription,
IN ULONG MaximumLength
)
/*++
Routine Description:
Sets up a DMA channel for future DMA operations.
Arguments:
Status - Returns the status of the request.
NdisDmaHandle - Returns a handle used to specify this channel to
future operations.
NdisAdapterHandle - handle returned by NdisRegisterAdapter.
DmaDescription - Details of the DMA channel.
MaximumLength - The maximum length DMA transfer that will be done
using this channel.
Return Value:
None.
--*/
{
//
// For registering this set of resources
//
PCM_RESOURCE_LIST Resources;
BOOLEAN Conflict;
//
// Needed to call HalGetAdapter.
//
DEVICE_DESCRIPTION DeviceDescription;
//
// Returned by HalGetAdapter.
//
PADAPTER_OBJECT AdapterObject;
//
// Map registers needed per channel.
//
ULONG MapRegistersNeeded;
//
// Map registers allowed per channel.
//
ULONG MapRegistersAllowed;
//
// Saves the structure we allocate for this channel.
//
PNDIS_DMA_BLOCK DmaBlock;
//
// Convert the handle to our internal structure.
PNDIS_ADAPTER_BLOCK AdapterBlock =
(PNDIS_ADAPTER_BLOCK) NdisAdapterHandle;
PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK) NdisAdapterHandle;
BOOLEAN IsAMiniport;
//
// Save our IRQL when we raise it to call IoAllocateAdapterChannel.
//
KIRQL OldIrql;
ULONG NumberOfElements;
NTSTATUS NtStatus;
LARGE_INTEGER TimeoutValue;
IsAMiniport = (AdapterBlock->DeviceObject == NULL);
//
// First check if any bus access is allowed
//
if (((IsAMiniport ?
Miniport->BusType :
AdapterBlock->BusType) == (NDIS_INTERFACE_TYPE)-1) ||
((IsAMiniport ?
Miniport->BusNumber :
AdapterBlock->BusNumber) == (ULONG)-1))
{
*Status = NDIS_STATUS_FAILURE;
return;
}
//
// First check for resource conflict by expanding current resource list,
// adding in the mapped space, and then re-submitting the resource list.
//
if ((IsAMiniport ? Miniport->Resources : AdapterBlock->Resources) != NULL)
{
NumberOfElements =
(IsAMiniport ?
Miniport->Resources->List[0].PartialResourceList.Count :
AdapterBlock->Resources->List[0].PartialResourceList.Count) + 1;
}
else
{
NumberOfElements = 1;
}
//
// First check for resource conflict by expanding current resource list,
// adding in the mapped space, and then re-submitting the resource list.
//
Resources = (PCM_RESOURCE_LIST)ALLOC_FROM_POOL(sizeof(CM_RESOURCE_LIST) +
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) *
NumberOfElements,
NDIS_TAG_RSRC_LIST);
if (Resources == NULL)
{
*Status = NDIS_STATUS_RESOURCES;
return;
}
if ((IsAMiniport ? Miniport->Resources : AdapterBlock->Resources) != NULL)
{
CopyMemory(Resources,
(IsAMiniport ? Miniport->Resources : AdapterBlock->Resources),
sizeof(CM_RESOURCE_LIST) +
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) *
(NumberOfElements - 1));
}
else
{
//
// Setup initial resource info
//
ASSERT(IsAMiniport);
Resources->Count = 1;
Resources->List[0].InterfaceType = Miniport->AdapterType;
Resources->List[0].BusNumber = Miniport->BusNumber;
Resources->List[0].PartialResourceList.Version = 0;
Resources->List[0].PartialResourceList.Revision = 0;
Resources->List[0].PartialResourceList.Count = 0;
}
//
// Setup DMA Channel
//
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].Type =
CmResourceTypeDma;
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].ShareDisposition =
CmResourceShareDeviceExclusive;
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].Flags =
0;
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].u.Dma.Channel =
(IsAMiniport ? Miniport->ChannelNumber :
(DmaDescription->DmaChannelSpecified ?
DmaDescription->DmaChannel : AdapterBlock->ChannelNumber));
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].u.Dma.Port =
DmaDescription->DmaPort;
Resources->List[0].PartialResourceList.Count++;
//
// Make the call
//
*Status = IoReportResourceUsage(NULL,
(IsAMiniport ?
Miniport->DriverHandle->NdisDriverInfo->NdisWrapperDriver :
AdapterBlock->MacHandle->NdisMacInfo->NdisWrapperDriver),
NULL,
0,
(IsAMiniport ? Miniport->DeviceObject : AdapterBlock->DeviceObject),
Resources,
sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * Resources->List[0].PartialResourceList.Count,
TRUE,
&Conflict);
if ((IsAMiniport ? Miniport->Resources : AdapterBlock->Resources) != NULL)
{
FREE_POOL((IsAMiniport ? Miniport->Resources : AdapterBlock->Resources));
}
if (IsAMiniport)
{
Miniport->Resources = Resources;
}
else
{
AdapterBlock->Resources = Resources;
}
//
// Check for conflict.
//
if (Conflict || (*Status != STATUS_SUCCESS))
{
if (Conflict)
{
//
// Log an error
//
PIO_ERROR_LOG_PACKET errorLogEntry;
ULONG i;
ULONG StringSize;
PUCHAR Place;
PWCH baseFileName;
WCHAR Character;
ULONG Value;
baseFileName = (IsAMiniport ?
Miniport->MiniportName.Buffer :
AdapterBlock->AdapterName.Buffer);
//
// Parse out the path name, leaving only the device name.
//
for (i = 0;
i < (IsAMiniport ? Miniport->MiniportName.Length :
AdapterBlock->AdapterName.Length)
/ sizeof(WCHAR);
i++)
{
//
// If s points to a directory separator, set baseFileName to
// the character after the separator.
//
if ((IsAMiniport ?
Miniport->MiniportName.Buffer[i] :
AdapterBlock->AdapterName.Buffer[i]) == OBJ_NAME_PATH_SEPARATOR)
{
baseFileName = (IsAMiniport ?
&(Miniport->MiniportName.Buffer[++i]) :
&(AdapterBlock->AdapterName.Buffer[++i]));
}
}
StringSize = (IsAMiniport ?
Miniport->MiniportName.MaximumLength :
AdapterBlock->AdapterName.MaximumLength) -
(((ULONG)baseFileName) -
(IsAMiniport ?
((ULONG)Miniport->MiniportName.Buffer) :
((ULONG)AdapterBlock->AdapterName.Buffer)));
errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
(IsAMiniport ?
Miniport->DeviceObject :
AdapterBlock->DeviceObject),
(UCHAR)(sizeof(IO_ERROR_LOG_PACKET) +
StringSize +
6)); // wstrlen("99") * sizeof(WHCAR) + sizeof(UNICODE_NULL)
if (errorLogEntry != NULL)
{
errorLogEntry->ErrorCode = EVENT_NDIS_DMA_CONFLICT;
//
// store the time
//
errorLogEntry->MajorFunctionCode = 0;
errorLogEntry->RetryCount = 0;
errorLogEntry->UniqueErrorValue = 0;
errorLogEntry->FinalStatus = 0;
errorLogEntry->SequenceNumber = 0;
errorLogEntry->IoControlCode = 0;
//
// Set string information
//
if (StringSize != 0)
{
errorLogEntry->NumberOfStrings = 1;
errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET);
CopyMemory(((PUCHAR)errorLogEntry) + sizeof(IO_ERROR_LOG_PACKET),
(PVOID)baseFileName,
StringSize);
Place = ((PUCHAR)errorLogEntry) +
sizeof(IO_ERROR_LOG_PACKET) +
StringSize;
}
else
{
Place = ((PUCHAR)errorLogEntry) +
sizeof(IO_ERROR_LOG_PACKET);
errorLogEntry->NumberOfStrings = 0;
}
errorLogEntry->NumberOfStrings++;
//
// Put in dma channel
//
Value = (IsAMiniport ? Miniport->ChannelNumber :
AdapterBlock->ChannelNumber);
//
// Convert value
//
// I couldn't think of a better way to do this (with some
// loop). If you find one, plz put it in.
//
if (Value > 9)
{
Character = L'0' + (WCHAR)(Value / 10);
memcpy((PVOID)Place, (PVOID)&Character, sizeof(WCHAR));
Place += sizeof(WCHAR);
Value -= 10;
}
Character = L'0' + (WCHAR)Value;
memcpy((PVOID)Place, (PVOID)&Character, sizeof(WCHAR));
Place += sizeof(WCHAR);
Character = UNICODE_NULL;
memcpy((PVOID)Place, (PVOID)&Character, sizeof(WCHAR));
//
// write it out
//
IoWriteErrorLogEntry(errorLogEntry);
}
*Status = NDIS_STATUS_RESOURCE_CONFLICT;
return;
}
*Status = NDIS_STATUS_FAILURE;
return;
}
//
// 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 =
(BOOLEAN)(IsAMiniport ?
MINIPORT_TEST_FLAG(Miniport, fMINIPORT_BUS_MASTER) : FALSE);
DeviceDescription.ScatterGather =
(BOOLEAN)(IsAMiniport ?
MINIPORT_TEST_FLAG(Miniport, fMINIPORT_BUS_MASTER) : FALSE);
DeviceDescription.DemandMode = DmaDescription->DemandMode;
DeviceDescription.AutoInitialize = DmaDescription->AutoInitialize;
DeviceDescription.Dma32BitAddresses =
(BOOLEAN)(IsAMiniport ?
MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DMA_32_BIT_ADDRESSES) : FALSE);
DeviceDescription.BusNumber = (IsAMiniport ? Miniport->BusNumber : AdapterBlock->BusNumber);
DeviceDescription.DmaChannel = (IsAMiniport ? Miniport->ChannelNumber :
(DmaDescription->DmaChannelSpecified ?
DmaDescription->DmaChannel : AdapterBlock->ChannelNumber));
DeviceDescription.InterfaceType = (IsAMiniport ? Miniport->BusType : AdapterBlock->BusType);
DeviceDescription.DmaWidth = DmaDescription->DmaWidth;
DeviceDescription.DmaSpeed = DmaDescription->DmaSpeed;
DeviceDescription.MaximumLength = MaximumLength;
DeviceDescription.DmaPort = DmaDescription->DmaPort;
MapRegistersNeeded = ((MaximumLength - 2) / PAGE_SIZE) + 2;
//
// Get the adapter object.
//
AdapterObject = HalGetAdapter (&DeviceDescription, &MapRegistersAllowed);
if ((AdapterObject == NULL) || (MapRegistersAllowed < MapRegistersNeeded))
{
*Status = NDIS_STATUS_RESOURCES;
return;
}
//
// Allocate storage for our DMA block.
//
DmaBlock = (PNDIS_DMA_BLOCK)ALLOC_FROM_POOL(sizeof(NDIS_DMA_BLOCK), NDIS_TAG_DMA);
if (DmaBlock == (PNDIS_DMA_BLOCK)NULL)
{
*Status = NDIS_STATUS_RESOURCES;
return;
}
//
// Use this event to tell us when ndisAllocationExecutionRoutine
// has been called.
//
INITIALIZE_EVENT(&DmaBlock->AllocationEvent);
//
// We save this to call IoFreeAdapterChannel later.
//
DmaBlock->SystemAdapterObject = AdapterObject;
//
// Now allocate the adapter channel.
//
RAISE_IRQL_TO_DISPATCH(&OldIrql);
NtStatus = IoAllocateAdapterChannel(
AdapterObject,
(IsAMiniport ? Miniport->DeviceObject : AdapterBlock->DeviceObject),
MapRegistersNeeded,
ndisDmaExecutionRoutine,
(PVOID)DmaBlock);
LOWER_IRQL(OldIrql);
if (!NT_SUCCESS(NtStatus))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("NDIS DMA AllocateAdapterChannel: %lx\n", NtStatus));
FREE_POOL(DmaBlock);
*Status = NDIS_STATUS_RESOURCES;
return;
}
TimeoutValue.QuadPart = Int32x32To64(100 * 1000, -10000);
//
// ndisDmaExecutionRoutine will set this event
// when it has been called.
//
NtStatus = WAIT_FOR_OBJECT(&DmaBlock->AllocationEvent, &TimeoutValue);
if (NtStatus != STATUS_SUCCESS)
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("NDIS DMA AllocateAdapterChannel: %lx\n", NtStatus));
FREE_POOL(DmaBlock);
*Status = NDIS_STATUS_RESOURCES;
return;
}
RESET_EVENT(&DmaBlock->AllocationEvent);
//
// We now have the DMA channel allocated, we are done.
//
DmaBlock->InProgress = FALSE;
*NdisDmaHandle = (NDIS_HANDLE)DmaBlock;
*Status = NDIS_STATUS_SUCCESS;
}
VOID
NdisFreeDmaChannel(
IN NDIS_HANDLE NdisDmaHandle
)
/*++
Routine Description:
Frees a DMA channel allocated with NdisAllocateDmaChannel.
Arguments:
NdisDmaHandle - Handle returned by NdisAllocateDmaChannel, indicating the
DMA channel that is to be freed.
Return Value:
None.
--*/
{
KIRQL OldIrql;
PNDIS_DMA_BLOCK DmaBlock = (PNDIS_DMA_BLOCK)NdisDmaHandle;
RAISE_IRQL_TO_DISPATCH(&OldIrql);
IoFreeAdapterChannel (DmaBlock->SystemAdapterObject);
LOWER_IRQL(OldIrql);
FREE_POOL(DmaBlock);
}
VOID
NdisSetupDmaTransfer(
OUT PNDIS_STATUS Status,
IN PNDIS_HANDLE NdisDmaHandle,
IN PNDIS_BUFFER Buffer,
IN ULONG Offset,
IN ULONG Length,
IN BOOLEAN WriteToDevice
)
/*++
Routine Description:
Sets up the host DMA controller for a DMA transfer. The
DMA controller is set up to transfer the specified MDL.
Since we register all DMA channels as non-scatter/gather,
IoMapTransfer will ensure that the entire MDL is
in a single logical piece for transfer.
Arguments:
Status - Returns the status of the request.
NdisDmaHandle - Handle returned by NdisAllocateDmaChannel.
Buffer - An NDIS_BUFFER which describes the host memory involved in the
transfer.
Offset - An offset within buffer where the transfer should
start.
Length - The length of the transfer. VirtualAddress plus Length must not
extend beyond the end of the buffer.
WriteToDevice - TRUE for a download operation (host to adapter); FALSE
for an upload operation (adapter to host).
Return Value:
None.
--*/
{
PNDIS_DMA_BLOCK DmaBlock = (PNDIS_DMA_BLOCK)NdisDmaHandle;
PHYSICAL_ADDRESS LogicalAddress;
ULONG LengthMapped;
//
// Make sure another request is not in progress.
//
if (DmaBlock->InProgress)
{
*Status = NDIS_STATUS_RESOURCES;
return;
}
DmaBlock->InProgress = TRUE;
//
// Use IoMapTransfer to set up the transfer.
//
LengthMapped = Length;
LogicalAddress = IoMapTransfer(DmaBlock->SystemAdapterObject,
(PMDL)Buffer,
DmaBlock->MapRegisterBase,
(PUCHAR)(MDL_VA(Buffer)) + Offset,
&LengthMapped,
WriteToDevice);
if (LengthMapped != Length)
{
//
// Somehow the request could not be mapped competely,
// this should not happen for a non-scatter/gather adapter.
//
(VOID)IoFlushAdapterBuffers(DmaBlock->SystemAdapterObject,
(PMDL)Buffer,
DmaBlock->MapRegisterBase,
(PUCHAR)(MDL_VA(Buffer)) + Offset,
LengthMapped,
WriteToDevice);
DmaBlock->InProgress = FALSE;
*Status = NDIS_STATUS_RESOURCES;
}
else *Status = NDIS_STATUS_SUCCESS;
}
VOID
NdisCompleteDmaTransfer(
OUT PNDIS_STATUS Status,
IN PNDIS_HANDLE NdisDmaHandle,
IN PNDIS_BUFFER Buffer,
IN ULONG Offset,
IN ULONG Length,
IN BOOLEAN WriteToDevice
)
/*++
Routine Description:
Completes a previously started DMA transfer.
Arguments:
Status - Returns the status of the transfer.
NdisDmaHandle - Handle returned by NdisAllocateDmaChannel.
Buffer - An NDIS_BUFFER which was passed to NdisSetupDmaTransfer.
Offset - the offset passed to NdisSetupDmaTransfer.
Length - The length passed to NdisSetupDmaTransfer.
WriteToDevice - TRUE for a download operation (host to adapter); FALSE
for an upload operation (adapter to host).
Return Value:
None.
--*/
{
PNDIS_DMA_BLOCK DmaBlock = (PNDIS_DMA_BLOCK)NdisDmaHandle;
BOOLEAN Successful;
Successful = IoFlushAdapterBuffers(DmaBlock->SystemAdapterObject,
(PMDL)Buffer,
DmaBlock->MapRegisterBase,
(PUCHAR)(MDL_VA(Buffer)) + Offset,
Length,
WriteToDevice);
*Status = (Successful ? NDIS_STATUS_SUCCESS : NDIS_STATUS_RESOURCES);
DmaBlock->InProgress = FALSE;
}
VOID
NdisRegisterMac(
OUT PNDIS_STATUS Status,
OUT PNDIS_HANDLE NdisMacHandle,
IN NDIS_HANDLE NdisWrapperHandle,
IN NDIS_HANDLE MacMacContext,
IN PNDIS_MAC_CHARACTERISTICS MacCharacteristics,
IN UINT CharacteristicsLength
)
/*++
Routine Description:
Register an NDIS MAC.
Arguments:
Status - Returns the final status.
NdisMacHandle - Returns a handle referring to this MAC.
NdisWrapperHandle - Handle returned by NdisInitializeWrapper.
MacMacContext - Context for calling MACUnloadMac and MACAddAdapter.
MacCharacteritics - The NDIS_MAC_CHARACTERISTICS table.
CharacteristicsLength - The length of MacCharacteristics.
Return Value:
None.
--*/
{
PNDIS_WRAPPER_HANDLE NdisMacInfo = (PNDIS_WRAPPER_HANDLE)(NdisWrapperHandle);
PNDIS_MAC_BLOCK MacBlock;
UNICODE_STRING Us;
PWSTR pWch;
USHORT i;
UINT MemNeeded;
KIRQL OldIrql;
//
// check that this is an NDIS 3.0 MAC.
//
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("==>NdisRegisterMac\n"));
do
{
*NdisMacHandle = (NDIS_HANDLE)NULL;
if (NdisMacInfo == NULL)
{
*Status = NDIS_STATUS_FAILURE;
break;
}
IF_DBG(DBG_COMP_CONFIG, DBG_LEVEL_ERR)
{
BOOLEAN f = FALSE;
if (DbgIsNull(MacCharacteristics->OpenAdapterHandler))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("RegisterMac: Null OpenAdapterHandler \n"));
f = TRUE;
}
if (DbgIsNull(MacCharacteristics->CloseAdapterHandler))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("RegisterMac: Null CloseAdapterHandler \n"));
f = TRUE;
}
if (DbgIsNull(MacCharacteristics->SendHandler))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("RegisterMac: Null SendHandler \n"));
f = TRUE;
}
if (DbgIsNull(MacCharacteristics->TransferDataHandler))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("RegisterMac: Null TransferDataHandler \n"));
f = TRUE;
}
if (DbgIsNull(MacCharacteristics->ResetHandler))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("RegisterMac: Null ResetHandler \n"));
f = TRUE;
}
if (DbgIsNull(MacCharacteristics->RequestHandler))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("RegisterMac: Null RequestHandler \n"));
f = TRUE;
}
if (DbgIsNull(MacCharacteristics->QueryGlobalStatisticsHandler))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("RegisterMac: Null QueryGlobalStatisticsHandler \n"));
f = TRUE;
}
if (DbgIsNull(MacCharacteristics->UnloadMacHandler))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("RegisterMac: Null UnloadMacHandler \n"));
f = TRUE;
}
if (DbgIsNull(MacCharacteristics->AddAdapterHandler))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("RegisterMac: Null AddAdapterHandler \n"));
f = TRUE;
}
if (DbgIsNull(MacCharacteristics->RemoveAdapterHandler))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("RegisterMac: Null RemoveAdapterHandler \n"));
f = TRUE;
}
if (f)
DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR);
}
if ((MacCharacteristics->MajorNdisVersion != 3) ||
(MacCharacteristics->MinorNdisVersion != 0))
{
*Status = NDIS_STATUS_BAD_VERSION;
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("<==NdisRegisterMac\n"));
break;
}
//
// Check that CharacteristicsLength is enough.
//
if (CharacteristicsLength < sizeof(NDIS_MAC_CHARACTERISTICS))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("char len = %d < %d\n",
CharacteristicsLength,
sizeof(NDIS_MAC_CHARACTERISTICS)));
*Status = NDIS_STATUS_BAD_CHARACTERISTICS;
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("<==NdisRegisterMac\n"));
break;
}
//
// Allocate memory for the NDIS MAC block.
//
MemNeeded = sizeof(NDIS_MAC_BLOCK) + MacCharacteristics->Name.Length;
//
// Extract the base-name, determine its length and allocate that much more
//
Us = *(PUNICODE_STRING)(NdisMacInfo->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;
MacBlock = (PNDIS_MAC_BLOCK)ALLOC_FROM_POOL(MemNeeded, NDIS_TAG_MAC_BLOCK);
if (MacBlock == (PNDIS_MAC_BLOCK)NULL)
{
*Status = NDIS_STATUS_RESOURCES;
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("<==NdisRegisterMac\n"));
break;
}
ZeroMemory(MacBlock, MemNeeded);
MacBlock->Length = MemNeeded;
//
// Copy over the characteristics table.
//
CopyMemory((PVOID)&MacBlock->MacCharacteristics,
(PVOID)MacCharacteristics,
sizeof(NDIS_MAC_CHARACTERISTICS));
//
// Move buffer pointer to correct location (extra space at the end of
// the characteristics table)
//
MacBlock->MacCharacteristics.Name.Buffer = (PWSTR)((PUCHAR)MacBlock + sizeof(NDIS_MAC_BLOCK));
//
// Copy String over.
//
MacBlock->MacCharacteristics.Name.Length =
MacBlock->MacCharacteristics.Name.MaximumLength = MacCharacteristics->Name.Length;
CopyMemory(MacBlock->MacCharacteristics.Name.Buffer,
MacCharacteristics->Name.Buffer,
MacCharacteristics->Name.Length);
//
// Upcase the base-name and save it in the MiniBlock
//
MacBlock->BaseName.Buffer = (PWSTR)((PUCHAR)MacBlock->MacCharacteristics.Name.Buffer +
MacCharacteristics->Name.Length);
MacBlock->BaseName.Length = Us.Length;
MacBlock->BaseName.MaximumLength = Us.MaximumLength;
RtlUpcaseUnicodeString(&MacBlock->BaseName,
&Us,
FALSE);
//
// No adapters yet registered for this MAC.
//
MacBlock->AdapterQueue = (PNDIS_ADAPTER_BLOCK)NULL;
MacBlock->MacMacContext = MacMacContext;
//
// Set up unload handler
//
NdisMacInfo->NdisWrapperDriver->DriverUnload = ndisUnload;
//
// Set up shutdown handler
//
NdisMacInfo->NdisWrapperDriver->MajorFunction[IRP_MJ_SHUTDOWN] = ndisShutdown;
//
// Set up the handlers for this driver (they all do nothing).
//
NdisMacInfo->NdisWrapperDriver->MajorFunction[IRP_MJ_CREATE] = ndisCreateIrpHandler;
NdisMacInfo->NdisWrapperDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ndisDeviceControlIrpHandler;
NdisMacInfo->NdisWrapperDriver->MajorFunction[IRP_MJ_CLEANUP] = ndisSuccessIrpHandler;
NdisMacInfo->NdisWrapperDriver->MajorFunction[IRP_MJ_CLOSE] = ndisCloseIrpHandler;
MacBlock->NdisMacInfo = NdisMacInfo;
//
// Use this event to tell us when all adapters are removed from the mac
// during an unload
//
INITIALIZE_EVENT(&MacBlock->AdaptersRemovedEvent);
MacBlock->Unloading = FALSE;
NdisInitializeRef(&MacBlock->Ref);
// Lock the init code down now - before we take the lock below
InitReferencePackage();
//
// Put MAC on global list.
//
ACQUIRE_SPIN_LOCK(&ndisDriverListLock, &OldIrql);
MacBlock->NextMac = ndisMacDriverList;
ndisMacDriverList = MacBlock;
RELEASE_SPIN_LOCK(&ndisDriverListLock, OldIrql);
*NdisMacHandle = (NDIS_HANDLE)MacBlock;
if (NdisMacInfo->NdisWrapperConfigurationHandle)
{
*Status = ndisInitializeAllAdapterInstances(MacBlock, NULL);
if (*Status != NDIS_STATUS_SUCCESS)
{
*Status = NDIS_STATUS_FAILURE;
ndisDereferenceMac(MacBlock);
}
}
else
{
*Status = NDIS_STATUS_FAILURE;
}
InitDereferencePackage();
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("<==NdisRegisterMac\n"));
} while (FALSE);
ASSERT(CURRENT_IRQL < DISPATCH_LEVEL);
}
VOID
NdisDeregisterMac(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE NdisMacHandle
)
/*++
Routine Description:
Deregisters an NDIS MAC.
Arguments:
Status - Returns the status of the request.
NdisMacHandle - The handle returned by NdisRegisterMac.
Return Value:
None.
--*/
{
PNDIS_MAC_BLOCK OldMacP = (PNDIS_MAC_BLOCK)NdisMacHandle;
//
// If the MAC is already closing, return.
//
*Status = NDIS_STATUS_SUCCESS;
if (OldMacP == NULL)
{
return;
}
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("==>NdisDeregisterMac\n"));
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
(" Mac %wZ being deregistered\n",&OldMacP->MacCharacteristics.Name));
IF_DBG(DBG_COMP_CONFIG, DBG_LEVEL_ERR)
{
if (DbgIsNull(NdisMacHandle))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("DeregisterMac: Null Handle\n"));
DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR);
}
if (!DbgIsNonPaged(NdisMacHandle))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("DeregisterMac: Handle not in NonPaged Memory\n"));
DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR);
}
}
if (!NdisCloseRef(&OldMacP->Ref))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("<==NdisDeregisterMac\n"));
return;
}
ASSERT(OldMacP->AdapterQueue == (PNDIS_ADAPTER_BLOCK)NULL);
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("<==NdisDeregisterMac\n"));
}
NDIS_STATUS
NdisRegisterAdapter(
OUT PNDIS_HANDLE NdisAdapterHandle,
IN NDIS_HANDLE NdisMacHandle,
IN NDIS_HANDLE MacAdapterContext,
IN NDIS_HANDLE WrapperConfigurationContext,
IN PNDIS_STRING AdapterName,
IN PVOID AdapterInformation
)
/*++
Routine Description:
Register an NDIS adapter.
Arguments:
NdisAdapterHandle - Returns a handle referring to this adapter.
NdisMacHandle - A handle for a previously registered MAC.
MacAdapterContext - A context for calls into this MAC.
WrapperConfigurationContext - Context passed to MacAddAdapter.
AdapterName - The name the adapter should be registered under.
AdapterInformation - Contains adapter information. For future
use. NULL for the meantime. Storage for it
must be allocated by the caller.
Return Value:
The final status.
--*/
{
PNDIS_ADAPTER_BLOCK NewAdaptP = NULL;
PDEVICE_OBJECT TmpDeviceP = NULL;
PNDIS_WRAPPER_CONFIGURATION_HANDLE ConfigurationHandle;
PNDIS_MAC_BLOCK TmpMacP;
NTSTATUS NtStatus;
NDIS_STRING NdisAdapterName = { 0 };
PHYSICAL_ADDRESS PortAddress;
PHYSICAL_ADDRESS InitialPortAddress;
ULONG addressSpace;
PNDIS_ADAPTER_INFORMATION AdapterInfo = (PNDIS_ADAPTER_INFORMATION)AdapterInformation;
BOOLEAN Conflict, ValidBus;
PCM_RESOURCE_LIST Resources = NULL;
LARGE_INTEGER TimeoutValue;
BOOLEAN AllocateIndividualPorts = TRUE, DerefMacOnError = FALSE;
ULONG i, Size;
ULONG BusNumber;
NDIS_INTERFACE_TYPE BusType;
NDIS_STATUS Status;
UNICODE_STRING DeviceName, UpcaseDeviceName;
UNICODE_STRING SymbolicLink;
WCHAR SymLnkBuf[40];
KIRQL OldIrql;
ConfigurationHandle = (PNDIS_WRAPPER_CONFIGURATION_HANDLE)WrapperConfigurationContext;
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("==>NdisRegisterAdapter\n"));
IF_DBG(DBG_COMP_CONFIG, DBG_LEVEL_ERR)
{
BOOLEAN f = FALSE;
if (DbgIsNull(NdisMacHandle))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("RegisterAdapter: Null Handle\n"));
f = TRUE;
}
if (!DbgIsNonPaged(NdisMacHandle))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("RegisterAdapter: Handle not in NonPaged Memory\n"));
f = TRUE;
}
if (DbgIsNull(MacAdapterContext))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("RegisterAdapter: Null Context\n"));
f = TRUE;
}
if (!DbgIsNonPaged(MacAdapterContext))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("RegisterAdapter: Context not in NonPaged Memory\n"));
f = TRUE;
}
if (f)
DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR);
}
do
{
//
// Increment the MAC's refernce count.
//
if (!ndisReferenceMac((PNDIS_MAC_BLOCK)NdisMacHandle))
{
//
// The MAC is closing.
//
Status = NDIS_STATUS_CLOSING;
break;
}
DerefMacOnError = TRUE;
//
// Allocate the string structure and space for the string. This
// must be allocated from nonpaged pool, because it is touched by
// NdisWriteErrorLogEntry, which may be called from DPC level.
//
NdisAdapterName.Buffer = (PWSTR)ALLOC_FROM_POOL(AdapterName->MaximumLength,
NDIS_TAG_NAME_BUF);
if (NdisAdapterName.Buffer == NULL)
{
Status = NDIS_STATUS_RESOURCES;
break;
}
NdisAdapterName.MaximumLength = AdapterName->MaximumLength;
NdisAdapterName.Length = AdapterName->Length;
CopyMemory(NdisAdapterName.Buffer,
AdapterName->Buffer,
AdapterName->MaximumLength);
//
// Create a device object for this adapter.
//
NtStatus = IoCreateDevice(((PNDIS_MAC_BLOCK)NdisMacHandle)->NdisMacInfo->NdisWrapperDriver,
sizeof(NDIS_ADAPTER_BLOCK) +
ConfigurationHandle->DriverBaseName->Length +
sizeof(NDIS_WRAPPER_CONTEXT),
AdapterName,
FILE_DEVICE_PHYSICAL_NETCARD,
0,
FALSE, // exclusive flag
&TmpDeviceP);
if (NtStatus != STATUS_SUCCESS)
{
Status = NDIS_STATUS_DEVICE_FAILED;
break;
}
//
// Create symbolic link for the device
//
SymbolicLink.Buffer = SymLnkBuf;
SymbolicLink.Length = sizeof(L"\\DosDevices\\") - sizeof(WCHAR);
SymbolicLink.MaximumLength = sizeof(SymLnkBuf);
RtlCopyMemory(SymLnkBuf, L"\\DosDevices\\", sizeof(L"\\DosDevices\\"));
RtlAppendUnicodeStringToString(&SymbolicLink, ConfigurationHandle->DriverBaseName);
IoCreateSymbolicLink(&SymbolicLink, AdapterName);
//
// Initialize the NDIS adapter block in the device object extension
//
// *** NDIS_WRAPPER_CONTEXT has a higher alignment requirement than
// NDIS_ADAPTER_BLOCK, so we put it first in the extension.
//
ASSERT((sizeof(NDIS_WRAPPER_CONTEXT) & 3) <= (sizeof(NDIS_ADAPTER_BLOCK) & 3));
NewAdaptP = (PNDIS_ADAPTER_BLOCK)((PNDIS_WRAPPER_CONTEXT)TmpDeviceP->DeviceExtension + 1);
ZeroMemory(NewAdaptP, sizeof(NDIS_ADAPTER_BLOCK));
NewAdaptP->BaseName.Buffer = (PWSTR)((PUCHAR)NewAdaptP + sizeof(NDIS_ADAPTER_BLOCK));
NewAdaptP->BaseName.MaximumLength =
NewAdaptP->BaseName.Length = ConfigurationHandle->DriverBaseName->Length;
RtlUpcaseUnicodeString(&NewAdaptP->BaseName,
ConfigurationHandle->DriverBaseName,
FALSE);
NewAdaptP->DeviceObject = TmpDeviceP;
NewAdaptP->MacHandle = TmpMacP = (PNDIS_MAC_BLOCK)NdisMacHandle;
NewAdaptP->MacAdapterContext = MacAdapterContext;
NewAdaptP->AdapterName = NdisAdapterName;
NewAdaptP->OpenQueue = (PNDIS_OPEN_BLOCK)NULL;
NewAdaptP->WrapperContext = TmpDeviceP->DeviceExtension;
//
// Save the bus information in the adapter block
//
NewAdaptP->BusType = ConfigurationHandle->Db.BusType;
NewAdaptP->BusId = ConfigurationHandle->Db.BusId;
NewAdaptP->BusNumber = ConfigurationHandle->Db.BusNumber;
NewAdaptP->SlotNumber = ConfigurationHandle->Db.SlotNumber;
//
// Get the BusNumber and BusType from the context
//
BusNumber = ConfigurationHandle->ParametersQueryTable[3].DefaultLength;
if (ConfigurationHandle->ParametersQueryTable[3].DefaultType == (NDIS_INTERFACE_TYPE)-1)
{
BusType = (NDIS_INTERFACE_TYPE)-1;
}
else
{
BusType = AdapterInfo->AdapterType;
}
//
// Check that if there is no bus number or no bus type that the driver is not
// going to try to acquire any hardware resources
//
ValidBus = ((BusType != (NDIS_INTERFACE_TYPE)-1) && (BusNumber != (ULONG)-1));
if ((BusType == (NDIS_INTERFACE_TYPE)-1) || (BusNumber == (ULONG)-1))
{
if ((AdapterInfo != NULL) && ((AdapterInfo->NumberOfPortDescriptors != 0) || (AdapterInfo->Master)))
{
//
// Error out
//
Status = NDIS_STATUS_BAD_CHARACTERISTICS;
break;
}
}
//
// Free up previously assigned Resource memory
//
if ((BusType == NdisInterfacePci) &&
(BusNumber != -1) &&
(AdapterInfo != NULL) &&
(TmpMacP->PciAssignedResources != NULL))
{
TmpMacP->PciAssignedResources->Count = 0;
NtStatus = IoReportResourceUsage(NULL,
((PNDIS_MAC_BLOCK)NdisMacHandle)->NdisMacInfo->NdisWrapperDriver,
TmpMacP->PciAssignedResources,
sizeof(CM_RESOURCE_LIST),
NULL,
NULL,
0,
TRUE,
&Conflict);
FREE_POOL(TmpMacP->PciAssignedResources);
TmpMacP->PciAssignedResources = NULL;
}
//
// Calculate size of new buffer
//
Size = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) *
(AdapterInfo->NumberOfPortDescriptors +
(((AdapterInfo->Master == TRUE) && (AdapterInfo->AdapterType == NdisInterfaceIsa)) ? 1 : 0));
Resources = (PCM_RESOURCE_LIST)ALLOC_FROM_POOL(Size, NDIS_TAG_RSRC_LIST);
if (Resources == NULL)
{
//
// Error out
//
Status = NDIS_STATUS_RESOURCES;
break;
}
//
// Fix up counts
//
Resources->List[0].PartialResourceList.Count = 0;
//
// Setup resources for the ports
//
if (ValidBus)
{
if (AdapterInfo != NULL)
{
ULONG HighestPort;
ULONG LowestPort;
Resources->Count = 1;
Resources->List[0].InterfaceType = AdapterInfo->AdapterType;
Resources->List[0].BusNumber = BusNumber;
Resources->List[0].PartialResourceList.Version = 0;
Resources->List[0].PartialResourceList.Revision = 0;
NewAdaptP->Resources = Resources;
NewAdaptP->BusNumber = BusNumber;
NewAdaptP->BusType = BusType;
NewAdaptP->AdapterType = AdapterInfo->AdapterType;
NewAdaptP->Master = AdapterInfo->Master;
//
// NewAdaptP->InitialPort and NumberOfPorts refer to the
// union of all port mappings specified; the area must
// cover all possible ports. We scan the list, keeping track
// of the highest and lowest ports used.
//
if (AdapterInfo->NumberOfPortDescriptors > 0)
{
//
// Setup port
//
LowestPort = AdapterInfo->PortDescriptors[0].InitialPort;
HighestPort = LowestPort + AdapterInfo->PortDescriptors[0].NumberOfPorts;
if (AdapterInfo->PortDescriptors[0].PortOffset == NULL)
{
AllocateIndividualPorts = FALSE;
}
for (i = 0; i < AdapterInfo->NumberOfPortDescriptors; i++)
{
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count + i].Type =
CmResourceTypePort;
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count + i].ShareDisposition =
CmResourceShareDeviceExclusive;
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count + i].Flags =
(AdapterInfo->AdapterType == NdisInterfaceInternal)?
CM_RESOURCE_PORT_MEMORY : CM_RESOURCE_PORT_IO;
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count + i].u.Port.Start.QuadPart =
(ULONG)AdapterInfo->PortDescriptors[i].InitialPort;
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count + i].u.Port.Length =
AdapterInfo->PortDescriptors[i].NumberOfPorts;
if (AdapterInfo->PortDescriptors[i].PortOffset == NULL)
{
AllocateIndividualPorts = FALSE;
}
if (AdapterInfo->PortDescriptors[i].InitialPort < LowestPort)
{
LowestPort = AdapterInfo->PortDescriptors[i].InitialPort;
}
if ((AdapterInfo->PortDescriptors[i].InitialPort +
AdapterInfo->PortDescriptors[i].NumberOfPorts) > HighestPort)
{
HighestPort = AdapterInfo->PortDescriptors[i].InitialPort +
AdapterInfo->PortDescriptors[i].NumberOfPorts;
}
}
NewAdaptP->InitialPort = LowestPort;
NewAdaptP->NumberOfPorts = HighestPort - LowestPort;
}
else
{
NewAdaptP->NumberOfPorts = 0;
}
Resources->List[0].PartialResourceList.Count += AdapterInfo->NumberOfPortDescriptors;
}
else
{
//
// Error out
//
Status = NDIS_STATUS_FAILURE;
break;
}
}
NewAdaptP->BeingRemoved = FALSE;
if (ValidBus)
{
//
// Submit Resources
//
NtStatus = IoReportResourceUsage(NULL,
((PNDIS_MAC_BLOCK)NdisMacHandle)->NdisMacInfo->NdisWrapperDriver,
NULL,
0,
NewAdaptP->DeviceObject,
Resources,
sizeof(CM_RESOURCE_LIST) +
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) *
Resources->List[0].PartialResourceList.Count,
TRUE,
&Conflict);
//
// Check for conflict.
//
if (Conflict || (NtStatus != STATUS_SUCCESS))
{
if (Conflict)
{
//
// Log an error
//
PIO_ERROR_LOG_PACKET errorLogEntry;
ULONG StringSize;
PWCH baseFileName;
baseFileName = NewAdaptP->AdapterName.Buffer;
//
// Parse out the path name, leaving only the device name.
//
for (i = 0; i < NewAdaptP->AdapterName.Length / sizeof(WCHAR); i++)
{
//
// If s points to a directory separator, set baseFileName to
// the character after the separator.
//
if (NewAdaptP->AdapterName.Buffer[i] == OBJ_NAME_PATH_SEPARATOR)
{
baseFileName = &(NewAdaptP->AdapterName.Buffer[++i]);
}
}
StringSize = NewAdaptP->AdapterName.MaximumLength -
(((ULONG)baseFileName) - ((ULONG)NewAdaptP->AdapterName.Buffer)) ;
errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(TmpDeviceP,
(UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + StringSize));
if (errorLogEntry != NULL)
{
errorLogEntry->ErrorCode = EVENT_NDIS_IO_PORT_CONFLICT;
//
// store the time
//
errorLogEntry->MajorFunctionCode = 0;
errorLogEntry->RetryCount = 0;
errorLogEntry->UniqueErrorValue = 0;
errorLogEntry->FinalStatus = 0;
errorLogEntry->SequenceNumber = 0;
errorLogEntry->IoControlCode = 0;
//
// Set string information
//
if (StringSize != 0)
{
errorLogEntry->NumberOfStrings = 1;
errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET);
CopyMemory (((PUCHAR)errorLogEntry) + sizeof(IO_ERROR_LOG_PACKET),
(PVOID)baseFileName,
StringSize);
}
else
{
errorLogEntry->NumberOfStrings = 0;
}
//
// write it out
//
IoWriteErrorLogEntry(errorLogEntry);
}
Status = NDIS_STATUS_RESOURCE_CONFLICT;
break;
}
Status = NDIS_STATUS_FAILURE;
break;
}
//
// If port mapping is needed, we do that. If the result
// is in memory, we have to map it. We map only the
// ports specified in AdapterInformation; the default
// is to map the first 4K.
//
// Note that NumberOfPorts can only be 0 if AdapterInfo
// is provided and explicitly sets it to 0, so in that
// case it is OK to leave the adapter in a state where
// a call to NdisXXXPort will probably crash (because
// PortOffset will be undefined).
//
if (NewAdaptP->NumberOfPorts > 0)
{
if (AllocateIndividualPorts)
{
Status = NDIS_STATUS_SUCCESS;
//
// We get here if we are supposed to allocate ports on an
// individual bases -- which implies that the driver will
// be using the Raw functions.
//
// Get the system physical address for this card. The card uses
// I/O space, except for "internal" Jazz devices which use
// memory space.
//
for (i = 0; i < AdapterInfo->NumberOfPortDescriptors; i++)
{
addressSpace = (NewAdaptP->AdapterType == NdisInterfaceInternal) ? 0 : 1;
InitialPortAddress.LowPart = AdapterInfo->PortDescriptors[i].InitialPort;
InitialPortAddress.HighPart = 0;
if (!HalTranslateBusAddress(NewAdaptP->BusType, // InterfaceType
NewAdaptP->BusNumber, // BusNumber
InitialPortAddress, // Bus Address
&addressSpace, // AddressSpace
&PortAddress)) // Translated address
{
Status = NDIS_STATUS_FAILURE;
break;
}
if (addressSpace == 0)
{
//
// memory space
//
*(AdapterInfo->PortDescriptors[i].PortOffset) =
MmMapIoSpace(PortAddress,
AdapterInfo->PortDescriptors[i].NumberOfPorts,
FALSE);
if (*(AdapterInfo->PortDescriptors[i].PortOffset) == NULL)
{
Status = NDIS_STATUS_RESOURCES;
break;
}
}
else
{
//
// I/O space
//
*(AdapterInfo->PortDescriptors[i].PortOffset) = (PUCHAR)PortAddress.LowPart;
}
}
if (!NT_SUCCESS(Status))
break;
}
else
{
//
// The driver will not use the Raw functions, only the
// old NdisRead and NdisWrite port functions.
//
// Get the system physical address for this card. The card uses
// I/O space, except for "internal" Jazz devices which use
// memory space.
//
addressSpace = (NewAdaptP->AdapterType == NdisInterfaceInternal) ? 0 : 1;
InitialPortAddress.LowPart = NewAdaptP->InitialPort;
InitialPortAddress.HighPart = 0;
if (!HalTranslateBusAddress(NewAdaptP->BusType, // InterfaceType
NewAdaptP->BusNumber, // BusNumber
InitialPortAddress, // Bus Address
&addressSpace, // AddressSpace
&PortAddress)) // Translated address
{
Status = NDIS_STATUS_FAILURE;
break;
}
if (addressSpace == 0)
{
//
// memory space
//
NewAdaptP->InitialPortMapping = MmMapIoSpace(PortAddress,
NewAdaptP->NumberOfPorts,
FALSE);
if (NewAdaptP->InitialPortMapping == NULL)
{
Status = NDIS_STATUS_RESOURCES;
break;
}
NewAdaptP->InitialPortMapped = TRUE;
}
else
{
//
// I/O space
//
NewAdaptP->InitialPortMapping = (PUCHAR)PortAddress.LowPart;
NewAdaptP->InitialPortMapped = FALSE;
}
//
// PortOffset holds the mapped address of port 0.
//
NewAdaptP->PortOffset = NewAdaptP->InitialPortMapping - NewAdaptP->InitialPort;
}
}
else
{
//
// Technically should not allow this, but do it until
// all drivers register their info correctly.
//
NewAdaptP->PortOffset = 0;
}
}
//
// If the driver want to be called back now, use
// supplied callback routine.
//
if ((AdapterInfo != NULL) && (AdapterInfo->ActivateCallback != NULL))
{
Status = (*(AdapterInfo->ActivateCallback))((NDIS_HANDLE)NewAdaptP,
MacAdapterContext,
AdapterInfo->DmaChannel);
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
}
//
// Set information from AdapterInformation. The call back
// routine can set these values.
//
NewAdaptP->ChannelNumber = AdapterInfo->DmaChannel;
NewAdaptP->PhysicalMapRegistersNeeded = AdapterInfo->PhysicalMapRegistersNeeded;
NewAdaptP->MaximumPhysicalMapping = AdapterInfo->MaximumPhysicalMapping;
//
// Check for resource conflic on DmaChannel.
//
if (NewAdaptP->Master && ValidBus && (NewAdaptP->AdapterType == NdisInterfaceIsa))
{
//
// Put the DMA channel in the resource list.
//
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].Type =
CmResourceTypeDma;
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].ShareDisposition =
CmResourceShareDeviceExclusive;
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].Flags =
0;
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].u.Dma.Channel =
NewAdaptP->ChannelNumber;
Resources->List[0].PartialResourceList.PartialDescriptors[Resources->List[0].PartialResourceList.Count].u.Dma.Port =
0;
Resources->List[0].PartialResourceList.Count++;
//
// Submit Resources
//
NtStatus = IoReportResourceUsage(NULL,
((PNDIS_MAC_BLOCK)NdisMacHandle)->NdisMacInfo->NdisWrapperDriver,
NULL,
0,
NewAdaptP->DeviceObject,
Resources,
sizeof(CM_RESOURCE_LIST) +
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) *
Resources->List[0].PartialResourceList.Count,
TRUE,
&Conflict);
//
// Check for conflict.
//
if (Conflict || (NtStatus != STATUS_SUCCESS))
{
if (Conflict)
{
//
// Log an error
//
PIO_ERROR_LOG_PACKET errorLogEntry;
ULONG StringSize;
PWCH baseFileName;
baseFileName = NewAdaptP->AdapterName.Buffer;
//
// Parse out the path name, leaving only the device name.
//
for (i = 0; i < NewAdaptP->AdapterName.Length / sizeof(WCHAR); i++)
{
//
// If s points to a directory separator, set baseFileName to
// the character after the separator.
//
if (NewAdaptP->AdapterName.Buffer[i] == OBJ_NAME_PATH_SEPARATOR)
{
baseFileName = &(NewAdaptP->AdapterName.Buffer[++i]);
}
}
StringSize = NewAdaptP->AdapterName.MaximumLength -
(((ULONG)baseFileName) - ((ULONG)NewAdaptP->AdapterName.Buffer)) ;
errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(TmpDeviceP,
(UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + StringSize));
if (errorLogEntry != NULL)
{
if ((NewAdaptP->Master) &&
(NewAdaptP->AdapterType == Isa))
{
errorLogEntry->ErrorCode = EVENT_NDIS_PORT_OR_DMA_CONFLICT;
}
else
{
errorLogEntry->ErrorCode = EVENT_NDIS_IO_PORT_CONFLICT;
}
//
// store the time
//
errorLogEntry->MajorFunctionCode = 0;
errorLogEntry->RetryCount = 0;
errorLogEntry->UniqueErrorValue = 0;
errorLogEntry->FinalStatus = 0;
errorLogEntry->SequenceNumber = 0;
errorLogEntry->IoControlCode = 0;
//
// Set string information
//
if (StringSize != 0)
{
errorLogEntry->NumberOfStrings = 1;
errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET);
CopyMemory (((PUCHAR)errorLogEntry) + sizeof(IO_ERROR_LOG_PACKET),
(PVOID)baseFileName,
StringSize);
}
else
{
errorLogEntry->NumberOfStrings = 0;
}
//
// write it out
//
IoWriteErrorLogEntry(errorLogEntry);
}
Status = NDIS_STATUS_RESOURCE_CONFLICT;
break;
}
Status = NDIS_STATUS_FAILURE;
break;
}
}
//
// 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 ((NewAdaptP->Master) && ValidBus)
{
//
// 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 Status;
//
// Allocate storage for holding the appropriate
// information for each map register.
//
NewAdaptP->MapRegisters = (PMAP_REGISTER_ENTRY)ALLOC_FROM_POOL(sizeof(MAP_REGISTER_ENTRY) *
NewAdaptP->PhysicalMapRegistersNeeded,
NDIS_TAG_MAP_REG);
if (NewAdaptP->MapRegisters == (PMAP_REGISTER_ENTRY)NULL)
{
Status = NDIS_STATUS_RESOURCES;
break;
}
//
// Use this event to tell us when ndisAllocationExecutionRoutine
// has been called.
//
INITIALIZE_EVENT(&NewAdaptP->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 = NewAdaptP->BusNumber;
DeviceDescription.DmaChannel = NewAdaptP->ChannelNumber;
DeviceDescription.InterfaceType = NewAdaptP->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 (NewAdaptP->ChannelNumber > 4)
{
DeviceDescription.DmaWidth = Width16Bits;
}
else
{
DeviceDescription.DmaWidth = Width8Bits;
}
DeviceDescription.DmaSpeed = Compatible;
}
else if ((DeviceDescription.InterfaceType == NdisInterfaceMca) ||
(DeviceDescription.InterfaceType == NdisInterfaceEisa) ||
(DeviceDescription.InterfaceType == NdisInterfacePci))
{
DeviceDescription.Dma32BitAddresses = AdapterInfo->Dma32BitAddresses;
DeviceDescription.DmaPort = 0;
}
DeviceDescription.MaximumLength = NewAdaptP->MaximumPhysicalMapping;
//
// Determine how many map registers we need per channel.
//
MapRegistersPerChannel =
((NewAdaptP->MaximumPhysicalMapping - 2) / PAGE_SIZE) + 2;
//
// Get the adapter object.
//
AdapterObject = HalGetAdapter (&DeviceDescription, &MapRegistersAllowed);
if (AdapterObject == NULL)
{
Status = NDIS_STATUS_RESOURCES;
break;
}
ASSERT (MapRegistersAllowed >= MapRegistersPerChannel);
//
// We save this to call IoFreeMapRegisters later.
//
NewAdaptP->SystemAdapterObject = AdapterObject;
//
// Now loop, allocating an adapter channel each time, then
// freeing everything but the map registers.
//
for (i=0; i<NewAdaptP->PhysicalMapRegistersNeeded; i++)
{
NewAdaptP->CurrentMapRegister = i;
RAISE_IRQL_TO_DISPATCH(&OldIrql);
Status = IoAllocateAdapterChannel(AdapterObject,
NewAdaptP->DeviceObject,
MapRegistersPerChannel,
ndisAllocationExecutionRoutine,
(PVOID)NewAdaptP);
if (!NT_SUCCESS(Status))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("Failed to load driver because of\n"));
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("insufficient map registers.\n"));
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("AllocateAdapterChannel: %lx\n", Status));
FREE_POOL(Resources);
for (; i != 0; i--)
{
IoFreeMapRegisters(NewAdaptP->SystemAdapterObject,
NewAdaptP->MapRegisters[i-1].MapRegister,
MapRegistersPerChannel);
}
LOWER_IRQL(OldIrql);
Status = NDIS_STATUS_RESOURCES;
break;
}
LOWER_IRQL(OldIrql);
TimeoutValue.QuadPart = Int32x32To64(10 * 1000, -10000);
//
// ndisAllocationExecutionRoutine will set this event
// when it has gotten FirstTranslationEntry.
//
NtStatus = WAIT_FOR_OBJECT(&NewAdaptP->AllocationEvent, &TimeoutValue);
if (NtStatus != STATUS_SUCCESS)
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("NDIS DMA AllocateAdapterChannel: %lx\n", NtStatus));
FREE_POOL(Resources);
RAISE_IRQL_TO_DISPATCH(&OldIrql);
for (; i != 0; i--)
{
IoFreeMapRegisters(NewAdaptP->SystemAdapterObject,
NewAdaptP->MapRegisters[i-1].MapRegister,
MapRegistersPerChannel);
}
LOWER_IRQL(OldIrql);
Status = NDIS_STATUS_RESOURCES;
break;
}
RESET_EVENT(&NewAdaptP->AllocationEvent);
}
if (!NT_SUCCESS(Status))
break;
}
NdisInitializeRef(&NewAdaptP->Ref);
if (!ndisQueueAdapterOnMac(NewAdaptP, TmpMacP))
{
//
// The MAC is closing, undo what we have done.
//
if (NewAdaptP->Master)
{
ULONG MapRegistersPerChannel =
((NewAdaptP->MaximumPhysicalMapping - 2) / PAGE_SIZE) + 2;
for (i=0; i<NewAdaptP->PhysicalMapRegistersNeeded; i++)
{
RAISE_IRQL_TO_DISPATCH(&OldIrql);
IoFreeMapRegisters(NewAdaptP->SystemAdapterObject,
NewAdaptP->MapRegisters[i].MapRegister,
MapRegistersPerChannel);
LOWER_IRQL(OldIrql);
}
}
Status = NDIS_STATUS_CLOSING;
break;
}
//
// Add an extra reference because the wrapper is using the MAC
//
ndisReferenceAdapter(NewAdaptP);
MacReferencePackage();
*NdisAdapterHandle = (NDIS_HANDLE)NewAdaptP;
Status = NDIS_STATUS_SUCCESS;
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("<==NdisRegisterAdapter\n"));
} while (FALSE);
if (Status != NDIS_STATUS_SUCCESS)
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("<==NdisRegisterAdapter\n"));
if (NewAdaptP != NULL)
{
NdisWriteErrorLogEntry(NewAdaptP,
Status,
0);
}
if (DerefMacOnError)
{
ndisDereferenceMac(TmpMacP);
}
if (NdisAdapterName.Buffer != NULL)
{
FREE_POOL(NdisAdapterName.Buffer);
}
if (TmpDeviceP != NULL)
{
IoDeleteDevice(TmpDeviceP);
if (NewAdaptP->MapRegisters != NULL)
{
FREE_POOL(NewAdaptP->MapRegisters);
}
if (Resources != NULL)
{
FREE_POOL(Resources);
}
}
}
return Status;
}
NDIS_STATUS
NdisDeregisterAdapter(
IN NDIS_HANDLE NdisAdapterHandle
)
/*++
Routine Description:
Deregisters an NDIS adapter.
Arguments:
NdisAdapterHandle - The handle returned by NdisRegisterAdapter.
Return Value:
NDIS_STATUS_SUCCESS.
--*/
{
//
// KillAdapter does all the work.
//
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("==>NdisDeregisterAdapter\n"));
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
(" Deregistering Adapter %s\n",
((PNDIS_ADAPTER_BLOCK)NdisAdapterHandle)->AdapterName.Buffer));
IF_DBG(DBG_COMP_CONFIG, DBG_LEVEL_ERR)
{
if (DbgIsNull(NdisAdapterHandle))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("DeregisterAdapter: Null Handle\n"));
DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR);
}
if (!DbgIsNonPaged(NdisAdapterHandle))
{
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
("DeregisterAdapter: Handle not in NonPaged Memory\n"));
DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR);
}
}
ndisKillAdapter((PNDIS_ADAPTER_BLOCK)NdisAdapterHandle);
//
// Remove reference from wrapper
//
ndisDereferenceAdapter((PNDIS_ADAPTER_BLOCK)NdisAdapterHandle);
MacDereferencePackage();
DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
("<==NdisDeregisterAdapter\n"));
return NDIS_STATUS_SUCCESS;
}
VOID
NdisRegisterAdapterShutdownHandler(
IN NDIS_HANDLE NdisAdapterHandle,
IN PVOID ShutdownContext,
IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler
)
/*++
Routine Description:
Registers an NDIS adapter.
Arguments:
NdisAdapterHandle - The handle returned by NdisRegisterAdapter.
ShutdownContext - Context to pass the the handler, when called.
ShutdownHandler - The Handler for the Adapter, to be called on shutdown.
Return Value:
NDIS_STATUS_SUCCESS.
--*/
{
PNDIS_ADAPTER_BLOCK Adapter = (PNDIS_ADAPTER_BLOCK) NdisAdapterHandle;
PNDIS_WRAPPER_CONTEXT WrapperContext = Adapter->WrapperContext;
if (WrapperContext->ShutdownHandler == NULL)
{
//
// Store information
//
WrapperContext->ShutdownHandler = ShutdownHandler;
WrapperContext->ShutdownContext = ShutdownContext;
//
// Register our shutdown handler for either a system shutdown
// notification or a bugcheck.
//
IoRegisterShutdownNotification(Adapter->DeviceObject);
KeInitializeCallbackRecord(&WrapperContext->BugcheckCallbackRecord);
KeRegisterBugCheckCallback(
&WrapperContext->BugcheckCallbackRecord,// callback record.
(PVOID) ndisBugcheckHandler, // callback routine.
(PVOID) WrapperContext, // free form buffer.
sizeof(NDIS_WRAPPER_CONTEXT), // buffer size.
"Ndis mac"); // component id.
}
}
VOID
NdisDeregisterAdapterShutdownHandler(
IN NDIS_HANDLE NdisAdapterHandle
)
/*++
Routine Description:
Deregisters an NDIS adapter.
Arguments:
NdisAdapterHandle - The handle returned by NdisRegisterAdapter.
Return Value:
NDIS_STATUS_SUCCESS.
--*/
{
PNDIS_ADAPTER_BLOCK Adapter = (PNDIS_ADAPTER_BLOCK) NdisAdapterHandle;
PNDIS_WRAPPER_CONTEXT WrapperContext = Adapter->WrapperContext;
if (WrapperContext->ShutdownHandler != NULL)
{
//
// Clear information
//
WrapperContext->ShutdownHandler = NULL;
IoUnregisterShutdownNotification(Adapter->DeviceObject);
KeDeregisterBugCheckCallback(&WrapperContext->BugcheckCallbackRecord);
}
}
NDIS_STATUS
NdisPciAssignResources(
IN NDIS_HANDLE NdisMacHandle,
IN NDIS_HANDLE NdisWrapperHandle,
IN NDIS_HANDLE WrapperConfigurationContext,
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:
NdisMacHandle - Handle returned from NdisRegisterMac.
NdisWrapperHandle - Handle returned from NdisInitializeWrapper.
WrapperConfigurationContext - Handle passed to MacAddAdapter.
SlotNumber - Slot number of the device.
AssignedResources - The returned resources.
Return Value:
Status of the operation
--*/
{
NTSTATUS NdisStatus = NDIS_STATUS_FAILURE;
NTSTATUS NtStatus;
ULONG BusNumber;
NDIS_INTERFACE_TYPE BusType;
PRTL_QUERY_REGISTRY_TABLE KeyQueryTable;
PCM_RESOURCE_LIST AllocatedResources = NULL;
PNDIS_WRAPPER_HANDLE NdisMacInfo = (PNDIS_WRAPPER_HANDLE)NdisWrapperHandle;
//
// Get the BusNumber and the BusType from the Context here!!
//
KeyQueryTable = ((PNDIS_WRAPPER_CONFIGURATION_HANDLE)WrapperConfigurationContext)->ParametersQueryTable;
BusType = (NDIS_INTERFACE_TYPE)KeyQueryTable[3].DefaultType;
BusNumber = KeyQueryTable[3].DefaultLength;
NtStatus = HalAssignSlotResources((PUNICODE_STRING)(NdisMacInfo->NdisWrapperConfigurationHandle),
NULL,
NdisMacInfo->NdisWrapperDriver,
NULL,
BusType,
BusNumber,
SlotNumber,
&AllocatedResources);
*AssignedResources = NULL; // Assume failure
if (NtStatus == STATUS_SUCCESS)
{
//
// Store resources into the driver wide block
//
((PNDIS_MAC_BLOCK)NdisMacHandle)->PciAssignedResources = 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
//
KeyQueryTable[4].DefaultLength = SlotNumber;
NdisStatus = NDIS_STATUS_SUCCESS;
}
return NdisStatus;
}