Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1122 lines
28 KiB

/*++
Copyright (c) 2002 Microsoft Corporation
Module Name:
pdopnp.c
Abstract:
This module contains the code to handle
the IRP_MJ_PNP dispatches for the PDOs
enumerated by the SD bus driver
Authors:
Neil Sandlin (neilsa) 1-Jan-2002
Environment:
Kernel mode only
Notes:
Revision History:
--*/
#include "pch.h"
//
// Internal References
//
NTSTATUS
SdbusPdoDeviceCapabilities(
IN PDEVICE_OBJECT Pdo,
IN PIRP Irp
);
NTSTATUS
SdbusPdoStartDevice(
IN PDEVICE_OBJECT Pdo,
IN PCM_RESOURCE_LIST AllocatedResources,
IN OUT PIRP Irp
);
NTSTATUS
SdbusPdoStopDevice(
IN PDEVICE_OBJECT Pdo
);
NTSTATUS
SdbusPdoRemoveDevice(
IN PDEVICE_OBJECT Pdo,
IN PIRP Irp
);
NTSTATUS
SdbusPdoQueryId(
IN PDEVICE_OBJECT Pdo,
IN PIRP Irp
);
NTSTATUS
SdbusPdoGetBusInformation(
IN PPDO_EXTENSION PdoExtension,
OUT PPNP_BUS_INFORMATION * BusInformation
);
NTSTATUS
SdbusQueryDeviceText(
IN PDEVICE_OBJECT Pdo,
IN OUT PIRP Irp
);
VOID
SdbusPdoGetDeviceInfSettings(
IN PPDO_EXTENSION PdoExtension
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, SdbusPdoPnpDispatch)
#pragma alloc_text(PAGE, SdbusPdoGetDeviceInfSettings)
#pragma alloc_text(PAGE, SdbusQueryDeviceText)
#pragma alloc_text(PAGE, SdbusPdoGetBusInformation)
#pragma alloc_text(PAGE, SdbusPdoStartDevice)
#pragma alloc_text(PAGE, SdbusPdoStopDevice)
#pragma alloc_text(PAGE, SdbusPdoRemoveDevice)
#pragma alloc_text(PAGE, SdbusPdoDeviceCapabilities)
#pragma alloc_text(PAGE, SdbusPdoGetDeviceInfSettings)
#endif
NTSTATUS
SdbusPdoPnpDispatch(
IN PDEVICE_OBJECT Pdo,
IN PIRP Irp
)
/*++
Routine Description:
This routine handles pnp requests
for the PDOs.
Arguments:
Pdo - pointer to the physical device object
Irp - pointer to the io request packet
Return Value:
status
--*/
{
PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status;
PAGED_CODE();
#if DBG
if (irpStack->MinorFunction > IRP_MN_PNP_MAXIMUM_FUNCTION) {
DebugPrint((SDBUS_DEBUG_PNP, "pdo %08x irp %08x Unknown minor function %x\n",
Pdo, Irp, irpStack->MinorFunction));
} else {
DebugPrint((SDBUS_DEBUG_PNP, "pdo %08x irp %08x --> %s\n",
Pdo, Irp, PNP_IRP_STRING(irpStack->MinorFunction)));
}
#endif
switch (irpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
status = SdbusPdoStartDevice(Pdo, irpStack->Parameters.StartDevice.AllocatedResources, Irp);
break;
case IRP_MN_QUERY_STOP_DEVICE:
status = STATUS_SUCCESS;
break;
case IRP_MN_CANCEL_STOP_DEVICE:
status = STATUS_SUCCESS;
break;
case IRP_MN_STOP_DEVICE:
status = SdbusPdoStopDevice(Pdo);
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
status = STATUS_SUCCESS;
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
status = STATUS_SUCCESS;
break;
case IRP_MN_REMOVE_DEVICE:
status = SdbusPdoRemoveDevice(Pdo, Irp);
break;
case IRP_MN_SURPRISE_REMOVAL:
// SdbusReleaseSocketPower(pdoExtension, NULL);
status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_ID:
status = SdbusPdoQueryId(Pdo, Irp);
break;
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_RESOURCES:
status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_DEVICE_RELATIONS: {
PDEVICE_RELATIONS deviceRelations;
if (irpStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) {
status = Irp->IoStatus.Status;
break;
}
deviceRelations = ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
if (deviceRelations == NULL) {
DebugPrint((SDBUS_DEBUG_FAIL,
"SdbusPdoPnpDispatch:unable to allocate memory for device relations\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
status = ObReferenceObjectByPointer(Pdo,
0,
NULL,
KernelMode);
if (!NT_SUCCESS(status)) {
ExFreePool(deviceRelations);
break;
}
deviceRelations->Count = 1;
deviceRelations->Objects[0] = Pdo;
Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
status = STATUS_SUCCESS;
break;
}
case IRP_MN_QUERY_CAPABILITIES:
status = SdbusPdoDeviceCapabilities(Pdo, Irp);
break;
case IRP_MN_QUERY_DEVICE_TEXT:
status = SdbusQueryDeviceText(Pdo, Irp);
if (status == STATUS_NOT_SUPPORTED ) {
//
// Do not change IRP status if this IRP is
// not handled
//
status = Irp->IoStatus.Status;
}
break;
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_BUS_INFORMATION:
status = SdbusPdoGetBusInformation(pdoExtension,
(PPNP_BUS_INFORMATION *) &Irp->IoStatus.Information);
break;
default:
//
// Retain the status
//
DebugPrint((SDBUS_DEBUG_PNP, "pdo %08x irp %08x Skipping unsupported irp\n", Pdo, Irp));
status = Irp->IoStatus.Status;
break;
}
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DebugPrint((SDBUS_DEBUG_PNP, "pdo %08x irp %08x comp %s %08x\n", Pdo, Irp,
STATUS_STRING(status), status));
return status;
}
NTSTATUS
SdbusPdoGetBusInformation(
IN PPDO_EXTENSION PdoExtension,
OUT PPNP_BUS_INFORMATION * BusInformation
)
/*++
Routine Description:
Returns the bus type information for the pc-card.
Bus type is GUID_BUS_TYPE_SDBUS(legacy type is SdbusBus) for R2 cards
Bus numbers are not implemented for SDBUS, so it's always 0
Arguments:
PdoExtension - pointer to device extension for the pc-card
BusInformation - pointer to the bus information structure that
needs to be filled in
Return value:
Status
--*/
{
PAGED_CODE();
*BusInformation = ExAllocatePool(PagedPool, sizeof (PNP_BUS_INFORMATION));
if (!*BusInformation) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(&((*BusInformation)->BusTypeGuid),
&GUID_BUS_TYPE_SD,
sizeof(GUID));
(*BusInformation)->LegacyBusType = InterfaceTypeUndefined;
(*BusInformation)->BusNumber = 0;
return STATUS_SUCCESS;
}
VOID
SdbusPdoGetDeviceInfSettings(
IN PPDO_EXTENSION PdoExtension
)
/*++
Routine Description:
This routine retrieves settings from the INF for this device.
Arguments:
DeviceExtension - Device extension of the Pc-Card
Return value:
None
--*/
{
NTSTATUS status;
UNICODE_STRING KeyName;
HANDLE instanceHandle;
UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
PKEY_VALUE_PARTIAL_INFORMATION value = (PKEY_VALUE_PARTIAL_INFORMATION) buffer;
ULONG length;
PAGED_CODE();
status = IoOpenDeviceRegistryKey(PdoExtension->DeviceObject,
PLUGPLAY_REGKEY_DRIVER,
KEY_READ,
&instanceHandle
);
if (NT_SUCCESS(status)) {
#if 0
//
// Look to see if SdbusExclusiveIrq is specified
//
RtlInitUnicodeString(&KeyName, L"SdbusExclusiveIrq");
status = ZwQueryValueKey(instanceHandle,
&KeyName,
KeyValuePartialInformation,
value,
sizeof(buffer),
&length);
//
// If the key doesn't exist, or zero was specified, it means that
// routing is ok
//
if (NT_SUCCESS(status) && (*(PULONG)(value->Data) != 0)) {
SetDeviceFlag(PdoExtension, SDBUS_PDO_EXCLUSIVE_IRQ);
}
#endif
ZwClose(instanceHandle);
}
}
NTSTATUS
SdbusQueryDeviceText(
IN PDEVICE_OBJECT Pdo,
IN OUT PIRP Irp
)
/*++
Routine Description:
Returns descriptive text information about the
PDO (location and device desc.)
Arguments:
Pdo - Pointer to the PC-Card's device object
Irp - IRP_MN_QUERY_DEVICE_TEXT Irp
Return Value:
STATUS_SUCCESS
STATUS_NOT_SUPPORTED - if not supported
--*/
{
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
UNICODE_STRING unicodeString;
ANSI_STRING ansiString;
UCHAR deviceText[128];
NTSTATUS status;
USHORT deviceTextLength;
PAGED_CODE();
if (irpStack->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription) {
if (pdoExtension->FunctionType == SDBUS_FUNCTION_TYPE_IO) {
PUCHAR mfg, prod;
if (pdoExtension->FdoExtension->CardData->MfgText[0]) {
mfg = pdoExtension->FdoExtension->CardData->MfgText;
} else {
mfg = "Generic";
}
if (pdoExtension->FdoExtension->CardData->ProductText[0]) {
prod = pdoExtension->FdoExtension->CardData->ProductText;
} else {
prod = "SD IO Device";
}
sprintf(deviceText, "%s %s", mfg, prod);
} else {
sprintf(deviceText, "%s", "Secure Digital Storage Device");
}
RtlInitAnsiString(&ansiString, deviceText);
deviceTextLength = (strlen(deviceText) + 1)*sizeof(WCHAR);
unicodeString.Buffer = ExAllocatePool(PagedPool, deviceTextLength);
if (unicodeString.Buffer == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
unicodeString.MaximumLength = deviceTextLength;
unicodeString.Length = 0;
status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, FALSE);
if (!NT_SUCCESS(status)) {
ExFreePool(unicodeString.Buffer);
return status;
}
unicodeString.Buffer[unicodeString.Length/sizeof(WCHAR)] = L'\0';
Irp->IoStatus.Information = (ULONG_PTR) unicodeString.Buffer;
status = STATUS_SUCCESS;
} else {
status = STATUS_NOT_SUPPORTED ;
}
return status;
}
NTSTATUS
SdbusGenerateDeviceId(
IN PPDO_EXTENSION PdoExtension,
OUT PUCHAR *DeviceId
)
/*++
This routines generates the device id for the given SD device.
Arguments:
Pdo - Pointer to the physical device object for the SD device
DeviceId - Pointer to the string in which device id is returned
Return Value
Status
--*/
{
PUCHAR deviceId;
PAGED_CODE();
deviceId = ExAllocatePool(PagedPool, SDBUS_MAXIMUM_DEVICE_ID_LENGTH);
if (deviceId == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
if (PdoExtension->FunctionType == SDBUS_FUNCTION_TYPE_IO) {
PSD_CARD_DATA cardData = PdoExtension->FdoExtension->CardData;
//
// IO card
//
sprintf(deviceId, "%s\\VID_%04x&PID_%04x",
"SD",
cardData->MfgId,
cardData->MfgInfo);
} else {
UCHAR productName[6];
UCHAR j;
PSD_CARD_DATA cardData = PdoExtension->FdoExtension->CardData;
//
// Memory card
//
sprintf(deviceId, "%s\\VID_%02x&OID_%04x&PID_%s&REV_%d.%d",
"SD",
cardData->SdCid.ManufacturerId,
cardData->SdCid.OemId,
cardData->ProductName,
(cardData->SdCid.Revision >> 4) , (cardData->SdCid.Revision & 0xF));
}
*DeviceId = deviceId;
return STATUS_SUCCESS;
}
NTSTATUS
SdbusGetHardwareIds(
IN PPDO_EXTENSION PdoExtension,
OUT PUNICODE_STRING HardwareIds
)
/*++
Routine Description:
This routine generates the hardware id's for the given sd device and returns them
as a Unicode multi-string.
Arguments:
Pdo - Pointer to device object representing the sd device
HardwareIds - Pointer to the unicode string which contains the hardware id's as a multi-string
Return value:
--*/
{
NTSTATUS status;
PSTR strings[4] = {NULL};
PUCHAR hwId;
UCHAR stringCount = 0;
PAGED_CODE();
//
// The first hardware id is identical to the device id
// Generate the device id
//
status = SdbusGenerateDeviceId(PdoExtension,
&strings[stringCount++]);
if (!NT_SUCCESS(status)) {
return status;
}
try {
//
// Add less specific IDs
//
if (PdoExtension->FunctionType == SDBUS_FUNCTION_TYPE_MEMORY) {
UCHAR productName[6];
UCHAR j;
PSD_CARD_DATA cardData = PdoExtension->FdoExtension->CardData;
status = STATUS_INSUFFICIENT_RESOURCES;
hwId = ExAllocatePool(PagedPool, SDBUS_MAXIMUM_DEVICE_ID_LENGTH);
if (!hwId) {
leave;
}
strings[stringCount++] = hwId;
//
// Memory card
//
sprintf(hwId, "%s\\VID_%02x&OID_%04x&PID_%s",
"SD",
cardData->SdCid.ManufacturerId,
cardData->SdCid.OemId,
cardData->ProductName);
}
status = SdbusStringsToMultiString(strings, stringCount, HardwareIds);
} finally {
while(stringCount != 0) {
ExFreePool(strings[--stringCount]);
}
}
return status;
}
NTSTATUS
SdbusGetCompatibleIds(
IN PPDO_EXTENSION PdoExtension,
OUT PUNICODE_STRING CompatibleIds
)
/*++
Routine Description:
This routine generates the compatible id's for the given sd device and returns them
as a Unicode multi-string.
Arguments:
Pdo - Pointer to device object representing the sd device
HardwareIds - Pointer to the unicode string which contains the hardware id's as a multi-string
Return value:
--*/
{
NTSTATUS status;
PSTR strings[1] = {NULL};
PUCHAR compatId;
UCHAR stringCount = 0;
PAGED_CODE();
try {
//
// Add the class ID
//
status = STATUS_INSUFFICIENT_RESOURCES;
compatId = ExAllocatePool(PagedPool, SDBUS_MAXIMUM_DEVICE_ID_LENGTH);
if (!compatId) {
leave;
}
strings[stringCount++] = compatId;
if (PdoExtension->FunctionType == SDBUS_FUNCTION_TYPE_MEMORY) {
sprintf(compatId, "%s\\CLASS_STORAGE", "SD");
} else {
PSD_CARD_DATA cardData = PdoExtension->FdoExtension->CardData;
PSD_FUNCTION_DATA functionData;
// find the right function data
for (functionData = cardData->FunctionData;
functionData != NULL;
functionData = functionData->Next) {
if (functionData->Function == PdoExtension->Function) break;
}
if (!functionData || (functionData->IoDeviceInterface == 0)) {
ASSERT(functionData != NULL);
status = STATUS_UNSUCCESSFUL;
leave;
}
sprintf(compatId, "%s\\CLASS_%02x",
"SD",
functionData->IoDeviceInterface);
DebugPrint((SDBUS_DEBUG_INFO, " %s\n", compatId));
}
status = SdbusStringsToMultiString(strings, stringCount, CompatibleIds);
} finally {
ASSERT(stringCount <= 1);
while(stringCount != 0) {
ExFreePool(strings[--stringCount]);
}
}
return status;
}
NTSTATUS
SdbusGetInstanceId(
IN PPDO_EXTENSION PdoExtension,
OUT PUNICODE_STRING InstanceId
)
/*++
Routine Description:
This routine generates a unique instance id (1 upwards) for the supplied
PC-Card which is guaranteed not to clash with any other instance ids under
the same pcmcia controller, for the same type of card.
A new instance id is computed only if it was not already present for the PC-Card.
Arguments:
Pdo - Pointer to the device object representing the PC-Card
InstanceId - Pointer to a unicode string which will contain the generated
instance id.
Memory for the unicode string allocated by this routine.
Caller's responsibility to free it .
Return value:
STATUS_SUCCESS
STATUS_UNSUCCESSFUL - Currently there's a cap on the maximum value of instance id - 999999
This status returned only if more than 999999 PC-Cards exist under
this PCMCIA controller!
Any other status - Something failed in the string allocation/conversion
--*/
{
ULONG instance;
NTSTATUS status;
ANSI_STRING sizeString;
ASSERT(InstanceId);
//
// Allocate memory for the unicode string
// Maximum of 6 digits in the instance..
//
RtlInitAnsiString(&sizeString, "123456");
status = RtlAnsiStringToUnicodeString(InstanceId, &sizeString, TRUE);
if (!NT_SUCCESS(status)) {
return status;
}
status = RtlIntegerToUnicodeString(999, 10, InstanceId);
if (!NT_SUCCESS(status)) {
RtlFreeUnicodeString(InstanceId);
}
return status;
}
NTSTATUS
SdbusPdoQueryId(
IN PDEVICE_OBJECT Pdo,
IN PIRP Irp
)
/*++
Routine Description:
Returns descriptive text information about the
PDO (location and device desc.)
Arguments:
Pdo - Pointer to the SD-Card's device object
Irp - IRP_MN_QUERY_DEVICE_TEXT Irp
Return Value:
STATUS_SUCCESS
STATUS_NOT_SUPPORTED - if not supported
--*/
{
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
UNICODE_STRING unicodeString;
ANSI_STRING ansiString;
UCHAR deviceText[128];
NTSTATUS status;
USHORT deviceTextLength;
UNICODE_STRING unicodeId;
PUCHAR deviceId;
PAGED_CODE();
status = Irp->IoStatus.Status;
RtlInitUnicodeString(&unicodeId, NULL);
switch (irpStack->Parameters.QueryId.IdType) {
case BusQueryDeviceID:
DebugPrint((SDBUS_DEBUG_INFO, " Device Id for pdo %x\n", Pdo));
status = SdbusGenerateDeviceId(pdoExtension, &deviceId);
if (!NT_SUCCESS(status)) {
break;
}
DebugPrint((SDBUS_DEBUG_INFO, "pdo %08x Device Id=%s\n", Pdo, deviceId));
RtlInitAnsiString(&ansiString, deviceId);
status = RtlAnsiStringToUnicodeString(&unicodeId, &ansiString, TRUE);
ExFreePool(deviceId);
if (NT_SUCCESS(status)) {
Irp->IoStatus.Information = (ULONG_PTR) unicodeId.Buffer;
}
break;
case BusQueryInstanceID:
DebugPrint((SDBUS_DEBUG_INFO, " Instance Id for pdo %x\n", Pdo));
status = SdbusGetInstanceId(pdoExtension, &unicodeId);
if (NT_SUCCESS(status)) {
Irp->IoStatus.Information = (ULONG_PTR) unicodeId.Buffer;
}
break;
case BusQueryHardwareIDs:
DebugPrint((SDBUS_DEBUG_INFO, " Hardware Ids for pdo %x\n", Pdo));
status = SdbusGetHardwareIds(pdoExtension, &unicodeId);
if (NT_SUCCESS(status)) {
Irp->IoStatus.Information = (ULONG_PTR) unicodeId.Buffer;
}
break;
case BusQueryCompatibleIDs:
DebugPrint((SDBUS_DEBUG_INFO, " Compatible Ids for pdo %x\n", Pdo));
status = SdbusGetCompatibleIds(pdoExtension, &unicodeId);
if (NT_SUCCESS(status)) {
Irp->IoStatus.Information = (ULONG_PTR) unicodeId.Buffer;
}
break;
}
return status;
}
NTSTATUS
SdbusPdoStartDevice(
IN PDEVICE_OBJECT Pdo,
IN PCM_RESOURCE_LIST ResourceList,
IN OUT PIRP Irp
)
/*++
Routine Description:
This routine attempts to start the PC-Card by configuring it with the supplied resources.
Arguments:
Pdo - Pointer to the device object representing the PC-Card which needs to be started
ResourceList - Pointer the list of assigned resources for the PC-Card
Return value:
STATUS_INSUFFICIENT_RESOURCES - Not sufficient resources supplied to start device/
could not allocate memory
STATUS_UNSUCCESSFUL - Supplied resources are invalid for this PC-Card
STATUS_SUCCESS - Configured and started the card successfully
--*/
{
PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
PFDO_EXTENSION fdoExtension = pdoExtension->FdoExtension;
NTSTATUS status;
PAGED_CODE();
if (IsDeviceStarted(pdoExtension)) {
//
// Already started..
//
return STATUS_SUCCESS;
}
if (IsDevicePhysicallyRemoved(pdoExtension)) {
return STATUS_DEVICE_DOES_NOT_EXIST;
}
status = SdbusExecuteWorkSynchronous(SDWP_INITIALIZE_FUNCTION, fdoExtension, pdoExtension);
if (NT_SUCCESS(status)) {
MarkDeviceStarted(pdoExtension);
MarkDeviceLogicallyInserted(pdoExtension);
}
return status;
}
NTSTATUS
SdbusPdoStopDevice(
IN PDEVICE_OBJECT Pdo
)
/*++
Routine Description:
This routine stops and deconfigures the given PC-Card
Arguments:
Pdo - Pointer to the device object representing the PC-Card which needs to be stopped
Return value:
STATUS_SUCCESS - PC-Card was already stopped, or stopped and deconfigured now successfully
--*/
{
PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
PAGED_CODE();
if (!IsDeviceStarted(pdoExtension)) {
return STATUS_SUCCESS;
}
//
// Need to deconfigure the controller
//
MarkDeviceNotStarted(pdoExtension);
return STATUS_SUCCESS;
}
NTSTATUS
SdbusPdoRemoveDevice(
IN PDEVICE_OBJECT Pdo,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
Return value:
--*/
{
PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
NTSTATUS status;
PAGED_CODE();
SdbusPdoStopDevice(Pdo);
// SdbusReleaseSocketPower(pdoExtension, NULL);
if (IsDevicePhysicallyRemoved(pdoExtension)) {
PFDO_EXTENSION fdoExtension = pdoExtension->FdoExtension;
PDEVICE_OBJECT curPdo, prevPdo;
PPDO_EXTENSION curPdoExt;
ULONG waitCount = 0;
#if 0
//
// Synchronize with power routines
// LATER: make these values adjustable
//
while(!SDBUS_TEST_AND_SET(&pdoExtension->DeletionLock)) {
SdbusWait(1000000);
if (waitCount++ > 20) {
ASSERT(waitCount <= 20);
break;
}
}
#endif
//
// Delink this Pdo from the FDO list.
//
for (curPdo = fdoExtension->PdoList, prevPdo = NULL; curPdo!=NULL; prevPdo = curPdo, curPdo=curPdoExt->NextPdoInFdoChain) {
curPdoExt = curPdo->DeviceExtension;
if (curPdo == Pdo) {
if (prevPdo) {
((PPDO_EXTENSION)prevPdo->DeviceExtension)->NextPdoInFdoChain = pdoExtension->NextPdoInFdoChain;
} else {
fdoExtension->PdoList = pdoExtension->NextPdoInFdoChain;
}
break;
}
}
SdbusCleanupPdo(Pdo);
//
// Delete..
//
if (!IsDeviceDeleted(pdoExtension)) {
MarkDeviceDeleted(pdoExtension);
IoDeleteDevice(Pdo);
}
} else {
//
// We will keep this Pdo around, since this is not physically ejected.
//
MarkDeviceLogicallyRemoved(pdoExtension);
}
return STATUS_SUCCESS;
}
VOID
SdbusCleanupPdo(
IN PDEVICE_OBJECT Pdo
)
/*++
Routine Description:
Arguments:
Return value:
--*/
{
PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
// currently nothing to do
}
NTSTATUS
SdbusPdoDeviceCapabilities(
IN PDEVICE_OBJECT Pdo,
IN PIRP Irp
)
/*++
Routine Description:
Obtains the device capabilities of the given SD device.
Arguments:
Pdo - Pointer to the device object for the pc-card
Irp - Pointer to the query device capabilities Irp
Return Value:
STATUS_SUCCESS - Capabilities obtained and recorded in the passed in pointer
STATUS_INSUFFICIENT_RESOURCES - Could not allocate memory to cache the capabilities
--*/
{
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_CAPABILITIES capabilities = irpStack->Parameters.DeviceCapabilities.Capabilities;
PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
PDEVICE_CAPABILITIES busCapabilities = &pdoExtension->FdoExtension->DeviceCapabilities;
PAGED_CODE();
//
// R2 card. Fill in the capabilities ourselves..
//
capabilities->Removable = TRUE;
capabilities->UniqueID = FALSE;
capabilities->EjectSupported = FALSE;
// capabilities->Address = pdoExtension->Socket->RegisterOffset;
capabilities->Address = 0;
// Don't know the UINumber, just leave it alone
if (busCapabilities->DeviceState[PowerSystemWorking] != PowerDeviceUnspecified) {
capabilities->DeviceState[PowerSystemWorking] = busCapabilities->DeviceState[PowerSystemWorking];
capabilities->DeviceState[PowerSystemSleeping1] = busCapabilities->DeviceState[PowerSystemSleeping1];
capabilities->DeviceState[PowerSystemSleeping2] = busCapabilities->DeviceState[PowerSystemSleeping2];
capabilities->DeviceState[PowerSystemSleeping3] = busCapabilities->DeviceState[PowerSystemSleeping3];
capabilities->DeviceState[PowerSystemHibernate] = busCapabilities->DeviceState[PowerSystemHibernate];
capabilities->DeviceState[PowerSystemShutdown] = busCapabilities->DeviceState[PowerSystemShutdown];
capabilities->SystemWake = MIN(PowerSystemSleeping3, busCapabilities->SystemWake);
capabilities->DeviceWake = PowerDeviceD0; // don't rely on FDO mungeing in the right thing for r2 cards
capabilities->D1Latency = busCapabilities->D1Latency;
capabilities->D2Latency = busCapabilities->D2Latency;
capabilities->D3Latency = busCapabilities->D3Latency;
} else {
capabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
capabilities->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;
capabilities->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;
capabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
capabilities->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
capabilities->DeviceState[PowerSystemShutdown] = PowerDeviceD3;
capabilities->SystemWake = PowerSystemUnspecified;
capabilities->DeviceWake = PowerDeviceD0; // don't rely on FDO mungeing in the right thing for r2 cards
capabilities->D1Latency = 0; // No latency - since we do nothing
capabilities->D2Latency = 0; //
capabilities->D3Latency = 100;
}
//
// Store these capabilities away..
//
RtlCopyMemory(&pdoExtension->DeviceCapabilities,
capabilities,
sizeof(DEVICE_CAPABILITIES));
return STATUS_SUCCESS;
}