|
|
/*++
Copyright (C) 1993-99 Microsoft Corporation
Module Name:
chanfdo.c
Abstract:
--*/
#include "ideport.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, ChannelAddDevice)
#pragma alloc_text(PAGE, ChannelAddChannel)
#pragma alloc_text(PAGE, ChannelStartDevice)
#pragma alloc_text(PAGE, ChannelStartChannel)
#pragma alloc_text(PAGE, ChannelCreateSymblicLinks)
#pragma alloc_text(PAGE, ChannelDeleteSymblicLinks)
#pragma alloc_text(PAGE, ChannelRemoveDevice)
#pragma alloc_text(PAGE, ChannelSurpriseRemoveDevice)
#pragma alloc_text(PAGE, ChannelStopDevice)
#pragma alloc_text(PAGE, ChannelRemoveChannel)
#pragma alloc_text(PAGE, ChannelQueryDeviceRelations)
#pragma alloc_text(PAGE, ChannelQueryBusRelation)
#pragma alloc_text(PAGE, ChannelQueryId)
#pragma alloc_text(PAGE, ChannelUsageNotification)
#pragma alloc_text(PAGE, DigestResourceList)
#pragma alloc_text(PAGE, ChannelQueryBusMasterInterface)
#pragma alloc_text(PAGE, ChannelQueryTransferModeInterface)
#pragma alloc_text(PAGE, ChannelUnbindBusMasterParent)
#pragma alloc_text(PAGE, ChannelQuerySyncAccessInterface)
#pragma alloc_text(PAGE, ChannelEnableInterrupt)
#pragma alloc_text(PAGE, ChannelDisableInterrupt)
#pragma alloc_text(PAGE, ChannelFilterResourceRequirements)
#pragma alloc_text(PAGE, ChannelQueryPnPDeviceState)
#pragma alloc_text(PAGE, ChannelQueryPcmciaParent)
#ifdef IDE_FILTER_PROMISE_TECH_RESOURCES
#pragma alloc_text(PAGE, ChannelFilterPromiseTechResourceRequirements)
#endif // IDE_FILTER_PROMISE_TECH_RESOURCES
#pragma alloc_text(NONPAGE, ChannelDeviceIoControl)
#pragma alloc_text(NONPAGE, ChannelRemoveDeviceCompletionRoutine)
#pragma alloc_text(NONPAGE, ChannelQueryIdCompletionRoutine)
#pragma alloc_text(NONPAGE, ChannelUsageNotificationCompletionRoutine)
#pragma alloc_text(NONPAGE, ChannelAcpiTransferModeSelect)
#pragma alloc_text(NONPAGE, ChannelRestoreTiming)
#pragma alloc_text(NONPAGE, ChannelStartDeviceCompletionRoutine)
#endif // ALLOC_PRAGMA
static ULONG AtapiNextIdePortNumber = 0;
NTSTATUS ChannelAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject ) { PFDO_EXTENSION fdoExtension;
return ChannelAddChannel(DriverObject, PhysicalDeviceObject, &fdoExtension); }
NTSTATUS ChannelAddChannel( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject, OUT PFDO_EXTENSION *FdoExtension ) { PDEVICE_OBJECT functionalDeviceObject; PFDO_EXTENSION fdoExtension; PPDO_EXTENSION pdoExtension; PDEVICE_OBJECT childDeviceObject; ULONG deviceExtensionSize; NTSTATUS status;
UNICODE_STRING deviceName; WCHAR deviceNameBuffer[64];
PAGED_CODE();
swprintf(deviceNameBuffer, DEVICE_OJBECT_BASE_NAME L"\\IdePort%d", AtapiNextIdePortNumber); RtlInitUnicodeString(&deviceName, deviceNameBuffer);
//
// We've been given the PhysicalDeviceObject for a IDE controller. Create the
// FunctionalDeviceObject. Our FDO will be nameless.
//
deviceExtensionSize = sizeof(FDO_EXTENSION) + sizeof(HW_DEVICE_EXTENSION);
status = IoCreateDevice( DriverObject, // our driver object
deviceExtensionSize, // size of our extension
&deviceName, // our name
FILE_DEVICE_CONTROLLER, // device type
FILE_DEVICE_SECURE_OPEN, // device characteristics
FALSE, // not exclusive
&functionalDeviceObject // store new device object here
);
if( !NT_SUCCESS( status )){
return status; }
fdoExtension = (PFDO_EXTENSION)functionalDeviceObject->DeviceExtension; RtlZeroMemory (fdoExtension, deviceExtensionSize);
fdoExtension->HwDeviceExtension = (PVOID)(fdoExtension + 1);
//
// We have our FunctionalDeviceObject, initialize it.
//
fdoExtension->AttacheePdo = PhysicalDeviceObject; fdoExtension->DriverObject = DriverObject; fdoExtension->DeviceObject = functionalDeviceObject;
// Dispatch Table
fdoExtension->DefaultDispatch = IdePortPassDownToNextDriver; fdoExtension->PnPDispatchTable = FdoPnpDispatchTable; fdoExtension->PowerDispatchTable = FdoPowerDispatchTable; fdoExtension->WmiDispatchTable = FdoWmiDispatchTable;
//
// Now attach to the PDO we were given.
//
fdoExtension->AttacheeDeviceObject = IoAttachDeviceToDeviceStack ( functionalDeviceObject, PhysicalDeviceObject ); if (fdoExtension->AttacheeDeviceObject == NULL) {
//
// Couldn't attach. Delete the FDO.
//
IoDeleteDevice (functionalDeviceObject); status = STATUS_UNSUCCESSFUL;
} else {
//
// fix up alignment requirement
//
functionalDeviceObject->AlignmentRequirement = fdoExtension->AttacheeDeviceObject->AlignmentRequirement; if (functionalDeviceObject->AlignmentRequirement < 1) { functionalDeviceObject->AlignmentRequirement = 1; }
fdoExtension->IdePortNumber = AtapiNextIdePortNumber; AtapiNextIdePortNumber++;
*FdoExtension = fdoExtension;
//
// Add this to the global FDO list.
//
IdeAddToFdoList (&IdeGlobalFdoList, fdoExtension);
CLRMASK (functionalDeviceObject->Flags, DO_DEVICE_INITIALIZING); }
DebugPrint((DBG_PNP, "DeviceObject %x returnd status %x from Addevice\n", PhysicalDeviceObject, status));
return status; }
NTSTATUS ChannelStartDevice ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PIO_STACK_LOCATION thisIrpSp; NTSTATUS status; PFDO_EXTENSION fdoExtension; PCM_RESOURCE_LIST resourceList; PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList; PCM_PARTIAL_RESOURCE_LIST partialResourceList; PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors; ULONG resourceListSize; ULONG i; PCM_RESOURCE_LIST resourceListForKeep = NULL; PIRP newIrp; KEVENT event; IO_STATUS_BLOCK ioStatusBlock;
ULONG parentResourceListSize; PCM_RESOURCE_LIST parentResourceList = NULL;
thisIrpSp = IoGetCurrentIrpStackLocation( Irp ); fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension;
ASSERT (!(fdoExtension->FdoState & FDOS_STARTED));
resourceList = thisIrpSp->Parameters.StartDevice.AllocatedResourcesTranslated;
//
// TEMP CODE for the time without a real PCI driver.
//
resourceListSize = 0;
if (resourceList) {
fullResourceList = resourceList->List;
for (i=0; i<resourceList->Count; i++) {
ULONG partialResourceListSize;
partialResourceList = &(fullResourceList->PartialResourceList); partialDescriptors = partialResourceList->PartialDescriptors;
partialResourceListSize = 0; for (i=0; i<partialResourceList->Count; i++) {
partialResourceListSize += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
if (partialDescriptors[i].Type == CmResourceTypeDeviceSpecific) {
partialResourceListSize += partialDescriptors[i].u.DeviceSpecificData.DataSize; } }
resourceListSize += partialResourceListSize + FIELD_OFFSET (CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors);
fullResourceList = (PCM_FULL_RESOURCE_DESCRIPTOR) (((UCHAR *) fullResourceList) + resourceListSize); } resourceListSize += FIELD_OFFSET (CM_RESOURCE_LIST, List); }
parentResourceListSize = sizeof (CM_RESOURCE_LIST) - sizeof (CM_FULL_RESOURCE_DESCRIPTOR) + FULL_RESOURCE_LIST_SIZE(3); // primary IO (2) + IRQ
parentResourceList = ExAllocatePool (PagedPool, parentResourceListSize);
if (!parentResourceList) {
status = STATUS_INSUFFICIENT_RESOURCES; goto GetOut; }
RtlZeroMemory (parentResourceList, parentResourceListSize);
KeInitializeEvent(&event, NotificationEvent, FALSE);
newIrp = IoBuildDeviceIoControlRequest ( IOCTL_IDE_GET_RESOURCES_ALLOCATED, fdoExtension->AttacheeDeviceObject, parentResourceList, parentResourceListSize, parentResourceList, parentResourceListSize, TRUE, &event, &ioStatusBlock);
if (newIrp == NULL) {
DebugPrint ((0, "Unable to allocate irp to bind with busmaster parent\n"));
status = STATUS_INSUFFICIENT_RESOURCES; goto GetOut;
} else {
status = IoCallDriver(fdoExtension->AttacheeDeviceObject, newIrp);
if (status == STATUS_PENDING) {
status = KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatusBlock.Status; } }
if (!NT_SUCCESS(status)) {
parentResourceListSize = 0;
} else {
parentResourceListSize = (ULONG)ioStatusBlock.Information; }
if (resourceListSize + parentResourceListSize) {
resourceListForKeep = ExAllocatePool (NonPagedPool, resourceListSize + parentResourceListSize);
} else {
resourceListForKeep = NULL; }
if (resourceListForKeep) {
PUCHAR d;
resourceListForKeep->Count = 0; d = (PUCHAR) resourceListForKeep->List;
if (resourceListSize) {
RtlCopyMemory ( d, resourceList->List, resourceListSize - FIELD_OFFSET (CM_RESOURCE_LIST, List) );
resourceListForKeep->Count = resourceList->Count; d += resourceListSize - FIELD_OFFSET (CM_RESOURCE_LIST, List); }
if (parentResourceListSize) {
RtlCopyMemory ( d, parentResourceList->List, parentResourceListSize - FIELD_OFFSET (CM_RESOURCE_LIST, List) );
resourceListForKeep->Count += parentResourceList->Count; } } else {
status = STATUS_INSUFFICIENT_RESOURCES; goto GetOut; }
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext (Irp);
Irp->IoStatus.Status = STATUS_SUCCESS ;
IoSetCompletionRoutine( Irp, ChannelStartDeviceCompletionRoutine, &event, TRUE, TRUE, TRUE );
//
// Pass the irp along
//
status = IoCallDriver(fdoExtension->AttacheeDeviceObject, Irp);
//
// Wait for it to come back...
//
if (status == STATUS_PENDING) {
KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
//
// Grab back the 'real' status
//
status = Irp->IoStatus.Status; }
if (!NT_SUCCESS(status)) {
ExFreePool (resourceListForKeep); goto GetOut; }
status = ChannelStartChannel (fdoExtension, resourceListForKeep);
if (!NT_SUCCESS(status)) {
ExFreePool (resourceListForKeep); goto GetOut; }
GetOut: if (parentResourceList) {
ExFreePool (parentResourceList); parentResourceList = NULL; }
Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status;
}
NTSTATUS ChannelStartDeviceCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp, IN OUT PVOID Context ) { PKEVENT event = (PKEVENT) Context;
//
// Signal the event
//
KeSetEvent( event, IO_NO_INCREMENT, FALSE );
//
// Always return MORE_PROCESSING_REQUIRED
// will complete it later
//
return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS ChannelStartChannel ( PFDO_EXTENSION FdoExtension, PCM_RESOURCE_LIST ResourceListToKeep ) { NTSTATUS status; PLOGICAL_UNIT_EXTENSION logUnitExtension; IDE_PATH_ID pathId; POWER_STATE newState; PCM_PARTIAL_RESOURCE_DESCRIPTOR irqPartialDescriptors; ULONG i;
#if DBG
{ PCM_RESOURCE_LIST resourceList; PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList; PCM_PARTIAL_RESOURCE_LIST partialResourceList; PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors; ULONG resourceListSize;
ULONG j;
resourceList = ResourceListToKeep; fullResourceList = resourceList->List; resourceListSize = 0;
DebugPrint ((1, "IdePort: Starting device: FDOe\n", FdoExtension));
for (i=0; i<resourceList->Count; i++) { partialResourceList = &(fullResourceList->PartialResourceList); partialDescriptors = fullResourceList->PartialResourceList.PartialDescriptors;
for (j=0; j<partialResourceList->Count; j++) { if (partialDescriptors[j].Type == CmResourceTypePort) { DebugPrint ((1, "IdePort: IO Port = 0x%x. Lenght = 0x%x\n", partialDescriptors[j].u.Port.Start.LowPart, partialDescriptors[j].u.Port.Length)); } else if (partialDescriptors[j].Type == CmResourceTypeInterrupt) { DebugPrint ((1, "IdePort: Int Level = 0x%x. Int Vector = 0x%x\n", partialDescriptors[j].u.Interrupt.Level, partialDescriptors[j].u.Interrupt.Vector)); } else { DebugPrint ((1, "IdePort: Unknown resource\n")); } } fullResourceList = (PCM_FULL_RESOURCE_DESCRIPTOR) (partialDescriptors + j); }
}
#endif // DBG
//
// Analyze the resources we are getting
//
status = DigestResourceList ( &FdoExtension->IdeResource, ResourceListToKeep, &irqPartialDescriptors ); if (!NT_SUCCESS(status)) {
goto GetOut;
} else {
PCONFIGURATION_INFORMATION configurationInformation; configurationInformation = IoGetConfigurationInformation();
if (FdoExtension->IdeResource.AtdiskPrimaryClaimed) { FdoExtension->HwDeviceExtension->PrimaryAddress = TRUE; FdoExtension->HwDeviceExtension->SecondaryAddress = FALSE; configurationInformation->AtDiskPrimaryAddressClaimed = TRUE; }
if (FdoExtension->IdeResource.AtdiskSecondaryClaimed) { FdoExtension->HwDeviceExtension->PrimaryAddress = FALSE; FdoExtension->HwDeviceExtension->SecondaryAddress = TRUE; configurationInformation->AtDiskSecondaryAddressClaimed = TRUE; } }
//
// Build io address structure.
//
AtapiBuildIoAddress( FdoExtension->IdeResource.TranslatedCommandBaseAddress, FdoExtension->IdeResource.TranslatedControlBaseAddress, &FdoExtension->HwDeviceExtension->BaseIoAddress1, &FdoExtension->HwDeviceExtension->BaseIoAddress2, &FdoExtension->HwDeviceExtension->BaseIoAddress1Length, &FdoExtension->HwDeviceExtension->BaseIoAddress2Length, &FdoExtension->HwDeviceExtension->MaxIdeDevice, &FdoExtension->HwDeviceExtension->MaxIdeTargetId);
//
// check for panasonic controller
//
FdoExtension->panasonicController = IdePortIsThisAPanasonicPCMCIACard(FdoExtension);
newState.DeviceState = PowerSystemWorking; status = IdePortIssueSetPowerState ( (PDEVICE_EXTENSION_HEADER) FdoExtension, SystemPowerState, newState, TRUE // sync call
); if (status == STATUS_INVALID_DEVICE_REQUEST) {
//
// The DeviceObject Below us does not support power irp,
// we will assume we are powered up
//
FdoExtension->SystemPowerState = PowerSystemWorking;
} else if (!NT_SUCCESS(status)) {
goto GetOut; }
newState.DeviceState = PowerDeviceD0; status = IdePortIssueSetPowerState ( (PDEVICE_EXTENSION_HEADER) FdoExtension, DevicePowerState, newState, TRUE // sync call
); if (status == STATUS_INVALID_DEVICE_REQUEST) {
//
// The DeviceObject Below us does not support power irp,
// we will assume we are powered up
//
FdoExtension->DevicePowerState = PowerDeviceD0;
} else if (!NT_SUCCESS(status)) {
goto GetOut; }
//
// Initialize "miniport" data structure
//
FdoExtension->HwDeviceExtension->InterruptMode = FdoExtension->IdeResource.InterruptMode;
#ifdef ENABLE_NATIVE_MODE
//
// Get parent's interrupt interface
//
ChannelQueryInterruptInterface ( FdoExtension );
#endif
//
// Connect our interrupt
//
if (irqPartialDescriptors) {
status = IoConnectInterrupt(&FdoExtension->InterruptObject, (PKSERVICE_ROUTINE) IdePortInterrupt, FdoExtension->DeviceObject, (PKSPIN_LOCK) NULL, irqPartialDescriptors->u.Interrupt.Vector, (KIRQL) irqPartialDescriptors->u.Interrupt.Level, (KIRQL) irqPartialDescriptors->u.Interrupt.Level, irqPartialDescriptors->Flags & CM_RESOURCE_INTERRUPT_LATCHED ? Latched : LevelSensitive, (BOOLEAN) (irqPartialDescriptors->ShareDisposition == CmResourceShareShared), irqPartialDescriptors->u.Interrupt.Affinity, FALSE); if (!NT_SUCCESS(status)) { DebugPrint((0, "IdePort: Can't connect interrupt %d\n", irqPartialDescriptors->u.Interrupt.Vector)); FdoExtension->InterruptObject = NULL; goto GetOut; }
#ifdef ENABLE_NATIVE_MODE
//
// Disconnect the parent ISR stub
//
if ( FdoExtension->InterruptInterface.PciIdeInterruptControl) {
DebugPrint((1, "IdePort: %d fdoe 0x%x Invoking disconnect\n", irqPartialDescriptors->u.Interrupt.Vector, FdoExtension ));
status = FdoExtension->InterruptInterface.PciIdeInterruptControl ( FdoExtension->InterruptInterface.Context, 1 ); ASSERT(NT_SUCCESS(status)); }
#endif
//
// Enable Interrupt
//
ChannelEnableInterrupt (FdoExtension); }
//
// Get parent's access token to serialize access with siblings (broken pci-ide)
//
ChannelQuerySyncAccessInterface ( FdoExtension );
if (FdoExtension->FdoState & FDOS_STOPPED) {
//
// we are restarting, no need to do the rest of start code
//
status = STATUS_SUCCESS; goto GetOut; } //
// Get parent's busmaster interface
//
ChannelQueryBusMasterInterface ( FdoExtension );
//
// Maintain a default timing table
//
if (FdoExtension->DefaultTransferModeTimingTable == NULL) {
ULONG length=0; PULONG transferModeTimingTable = ExAllocatePool(NonPagedPool, MAX_XFER_MODE*sizeof(ULONG));
if (transferModeTimingTable != NULL) { SetDefaultTiming(transferModeTimingTable, length); FdoExtension->DefaultTransferModeTimingTable = transferModeTimingTable; } else { status = STATUS_INSUFFICIENT_RESOURCES; goto GetOut; } } ASSERT(FdoExtension->DefaultTransferModeTimingTable);
//
// get an interface that tells parent to invalidate out resource requirement
//
ChannelQueryRequestProperResourceInterface ( FdoExtension );
//
// Create legacy object names
//
status = ChannelCreateSymblicLinks ( FdoExtension );
if (!NT_SUCCESS(status)) {
goto GetOut; }
//
// FDO Init Data
//
IdePortInitFdo (FdoExtension);
//
// Allocate reserve error log packets to log insufficient resource events
//
for (i=0;i<MAX_IDE_DEVICE;i++) {
if (FdoExtension->ReserveAllocFailureLogEntry[i] == NULL) { FdoExtension->ReserveAllocFailureLogEntry[i] = IoAllocateErrorLogEntry( FdoExtension->DeviceObject, ALLOC_FAILURE_LOGSIZE ); } }
//
// Pre-allocate memory for enumeration
//
if (!IdePreAllocEnumStructs(FdoExtension)) { status=STATUS_INSUFFICIENT_RESOURCES; goto GetOut; }
//
// Reserve pages to perform I/O under low memory conditions
//
if (FdoExtension->ReservedPages == NULL) {
FdoExtension->ReservedPages = MmAllocateMappingAddress( IDE_NUM_RESERVED_PAGES * PAGE_SIZE, 'PedI' );
ASSERT(FdoExtension->ReservedPages); }
GetOut: if (NT_SUCCESS(status)) {
//
// End of Init.
//
CLRMASK (FdoExtension->FdoState, FDOS_STOPPED); SETMASK (FdoExtension->FdoState, FDOS_STARTED);
if (FdoExtension->ResourceList) { ExFreePool(FdoExtension->ResourceList); FdoExtension->ResourceList = NULL; } FdoExtension->ResourceList = ResourceListToKeep;
} else {
ChannelRemoveChannel (FdoExtension); }
return status; }
NTSTATUS ChannelCreateSymblicLinks ( PFDO_EXTENSION FdoExtension ) { NTSTATUS status; ULONG i = 0; PULONG scsiportNumber;
UNICODE_STRING deviceName; WCHAR deviceNameBuffer[64];
UNICODE_STRING symbolicDeviceName; WCHAR symbolicDeviceNameBuffer[64];
swprintf(deviceNameBuffer, DEVICE_OJBECT_BASE_NAME L"\\IdePort%d", FdoExtension->IdePortNumber); RtlInitUnicodeString(&deviceName, deviceNameBuffer);
scsiportNumber = &IoGetConfigurationInformation()->ScsiPortCount;
do { swprintf(symbolicDeviceNameBuffer, L"\\Device\\ScsiPort%d", i); RtlInitUnicodeString(&symbolicDeviceName, symbolicDeviceNameBuffer);
status = IoCreateSymbolicLink( &symbolicDeviceName, &deviceName );
if (NT_SUCCESS (status)) {
swprintf(symbolicDeviceNameBuffer, L"\\DosDevices\\Scsi%d:", i); RtlInitUnicodeString(&symbolicDeviceName, symbolicDeviceNameBuffer);
IoAssignArcName ( &symbolicDeviceName, &deviceName );
break; } i += 1; } while(i <= *scsiportNumber);
if (NT_SUCCESS(status)) {
FdoExtension->SymbolicLinkCreated = TRUE; FdoExtension->ScsiPortNumber = i; (*scsiportNumber)++; }
return status; }
NTSTATUS ChannelDeleteSymblicLinks ( PFDO_EXTENSION FdoExtension ) { NTSTATUS status; ULONG i;
UNICODE_STRING deviceName; WCHAR deviceNameBuffer[64];
if (!FdoExtension->SymbolicLinkCreated) {
return STATUS_SUCCESS; }
swprintf(deviceNameBuffer, L"\\Device\\ScsiPort%d", FdoExtension->ScsiPortNumber); RtlInitUnicodeString(&deviceName, deviceNameBuffer);
IoDeleteSymbolicLink( &deviceName );
swprintf(deviceNameBuffer, L"\\DosDevices\\Scsi%d:", FdoExtension->ScsiPortNumber); RtlInitUnicodeString(&deviceName, deviceNameBuffer);
IoDeassignArcName(&deviceName);
FdoExtension->SymbolicLinkCreated = FALSE;
IoGetConfigurationInformation()->ScsiPortCount--;
return STATUS_SUCCESS; }
NTSTATUS ChannelSurpriseRemoveDevice ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PFDO_EXTENSION fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension; PPDO_EXTENSION pdoExtension; IDE_PATH_ID pathId; NTSTATUS status;
//
// all my childred should be surprise removed or removed
//
pathId.l = 0; while (pdoExtension = NextLogUnitExtensionWithTag ( fdoExtension, &pathId, TRUE, ChannelSurpriseRemoveDevice )) {
//ASSERT (pdoExtension->PdoState & (PDOS_SURPRISE_REMOVED | PDOS_REMOVED));
CLRMASK (pdoExtension->PdoState, PDOS_REPORTED_TO_PNP);
UnrefPdoWithTag( pdoExtension, ChannelSurpriseRemoveDevice ); }
status = ChannelRemoveChannel (fdoExtension); ASSERT (NT_SUCCESS(status));
Irp->IoStatus.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation (Irp); return IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp); }
NTSTATUS ChannelRemoveDevice ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PFDO_EXTENSION fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension; PPDO_EXTENSION pdoExtension; NTSTATUS status; KEVENT event;
IDE_PATH_ID pathId;
DebugPrint (( DBG_PNP, "fdoe 0x%x 0x%x got a STOP device\n", fdoExtension, fdoExtension->IdeResource.TranslatedCommandBaseAddress ));
//
// Remove from the FDO list.
//
IdeRemoveFromFdoList (&IdeGlobalFdoList, fdoExtension);
//
// Kill all the children if any
//
pathId.l = 0; while (pdoExtension = NextLogUnitExtensionWithTag ( fdoExtension, &pathId, TRUE, ChannelRemoveDevice )) {
if (pdoExtension->PdoState & PDOS_SURPRISE_REMOVED) {
CLRMASK (pdoExtension->PdoState, PDOS_REPORTED_TO_PNP); continue; }
FreePdoWithTag( pdoExtension, TRUE, TRUE, ChannelRemoveDevice ); }
status = ChannelRemoveChannel (fdoExtension); ASSERT (NT_SUCCESS(status));
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext (Irp);
IoSetCompletionRoutine( Irp, ChannelRemoveDeviceCompletionRoutine, &event, TRUE, TRUE, TRUE );
status = IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
IoDetachDevice (fdoExtension->AttacheeDeviceObject);
IoDeleteDevice (DeviceObject);
//return STATUS_SUCCESS;
return status; }
NTSTATUS ChannelRemoveDeviceCompletionRoutine ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { PKEVENT event = Context;
KeSetEvent(event, 0, FALSE);
return STATUS_SUCCESS; }
NTSTATUS ChannelStopDevice ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PFDO_EXTENSION fdoExtension;
fdoExtension = DeviceObject->DeviceExtension;
DebugPrint (( DBG_PNP, "fdoe 0x%x 0x%x got a STOP device\n", fdoExtension, fdoExtension->IdeResource.TranslatedCommandBaseAddress ));
//
// disable interrupt
//
ChannelDisableInterrupt (fdoExtension);
if (fdoExtension->InterruptObject) {
#ifdef ENABLE_NATIVE_MODE
//
// Reconnect the parent ISR stub
//
if (fdoExtension->InterruptInterface.PciIdeInterruptControl) {
NTSTATUS status;
DebugPrint((1, "fdoe 0x%x invoking reconnect\n", fdoExtension));
status = fdoExtension->InterruptInterface.PciIdeInterruptControl ( fdoExtension->InterruptInterface.Context, 0 ); ASSERT(NT_SUCCESS(status)); }
#endif
IoDisconnectInterrupt ( fdoExtension->InterruptObject );
fdoExtension->InterruptObject = 0;
}
if (fdoExtension->FdoState & FDOS_STARTED) {
//
// indicate we have been stopped only if we have started
//
CLRMASK (fdoExtension->FdoState, FDOS_STARTED); SETMASK (fdoExtension->FdoState, FDOS_STOPPED); }
Irp->IoStatus.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation (Irp); return IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp); }
NTSTATUS ChannelRemoveChannel ( PFDO_EXTENSION FdoExtension ) { PCONFIGURATION_INFORMATION configurationInformation; ULONG i;
configurationInformation = IoGetConfigurationInformation(); DebugPrint((1, "ChannelRemoveChannel for FDOe %x\n", FdoExtension));
if (FdoExtension->IdeResource.AtdiskPrimaryClaimed) { configurationInformation->AtDiskPrimaryAddressClaimed = FALSE; }
if (FdoExtension->IdeResource.AtdiskSecondaryClaimed) { configurationInformation->AtDiskSecondaryAddressClaimed = FALSE; } FdoExtension->IdeResource.AtdiskPrimaryClaimed = FALSE; FdoExtension->IdeResource.AtdiskSecondaryClaimed = FALSE; FdoExtension->HwDeviceExtension->PrimaryAddress = FALSE;
if ((FdoExtension->IdeResource.CommandBaseAddressSpace == MEMORY_SPACE) && (FdoExtension->IdeResource.TranslatedCommandBaseAddress)) {
MmUnmapIoSpace ( FdoExtension->IdeResource.TranslatedCommandBaseAddress, FdoExtension->HwDeviceExtension->BaseIoAddress1Length ); } FdoExtension->IdeResource.TranslatedCommandBaseAddress = 0;
if ((FdoExtension->IdeResource.ControlBaseAddressSpace == MEMORY_SPACE) && (FdoExtension->IdeResource.TranslatedControlBaseAddress)) {
MmUnmapIoSpace ( FdoExtension->IdeResource.TranslatedControlBaseAddress, 1 ); } FdoExtension->IdeResource.TranslatedControlBaseAddress = 0;
if (FdoExtension->InterruptObject) {
#ifdef ENABLE_NATIVE_MODE
//
// Reconnect the parent ISR stub
//
if (FdoExtension->InterruptInterface.PciIdeInterruptControl) {
NTSTATUS status;
DebugPrint((1, "fdoe 0x%x invoking reconnect\n", FdoExtension));
status = FdoExtension->InterruptInterface.PciIdeInterruptControl ( FdoExtension->InterruptInterface.Context, 0 ); ASSERT(NT_SUCCESS(status)); }
#endif
IoDisconnectInterrupt ( FdoExtension->InterruptObject );
FdoExtension->InterruptObject = 0; }
// unbind from the bm stuff if NECESSARY
// release parent's access token to serialize access with siblings (broken pci-ide)
if (FdoExtension->ResourceList) {
ExFreePool (FdoExtension->ResourceList); FdoExtension->ResourceList = NULL;
} else { DebugPrint((1, "ATAPI: Resource list for FDOe %x already freed\n", FdoExtension)); }
//
// Lock
//
ASSERT(InterlockedCompareExchange(&(FdoExtension->EnumStructLock), 1, 0) == 0);
//
// Free pre-allocated memory
//
IdeFreeEnumStructs(FdoExtension->PreAllocEnumStruct);
FdoExtension->PreAllocEnumStruct = NULL;
//
// Unlock
//
ASSERT(InterlockedCompareExchange(&(FdoExtension->EnumStructLock), 0, 1) == 1);
//
// Free the reserve error log entries
//
for (i=0; i< MAX_IDE_DEVICE; i++) { PVOID entry; PVOID currentValue;
entry = FdoExtension->ReserveAllocFailureLogEntry[i];
if (entry == NULL) { continue; } //
// We have to ensure that we are the only instance to use this
// event. To do so, we attempt to NULL the event in the driver
// extension. If somebody else beats us to it, they own the
// event and we have to give up.
//
currentValue = InterlockedCompareExchangePointer( &(FdoExtension->ReserveAllocFailureLogEntry[i]), NULL, entry );
if (entry != currentValue) { continue; }
// Note that you cannot ExFreePool the entry
// because Io returns an offset into the pool allocation, not the start.
// Use the API provided by Iomanager
IoFreeErrorLogEntry(entry); }
//
// Free the default timing table
//
if (FdoExtension->DefaultTransferModeTimingTable) {
ExFreePool(FdoExtension->DefaultTransferModeTimingTable);
FdoExtension->DefaultTransferModeTimingTable = NULL; FdoExtension->TransferModeInterface.TransferModeTimingTable = NULL; FdoExtension->TransferModeInterface.TransferModeTableLength =0; }
//
// Unmap the reserved mapping
//
if (FdoExtension->ReservedPages != NULL) {
MmFreeMappingAddress(FdoExtension->ReservedPages, 'PedI' ); FdoExtension->ReservedPages = NULL; }
ChannelDeleteSymblicLinks ( FdoExtension );
return STATUS_SUCCESS; }
NTSTATUS ChannelQueryDeviceRelations ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PFDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension; PIO_STACK_LOCATION thisIrpSp; PIDE_WORK_ITEM_CONTEXT workItemContext; PENUMERATION_STRUCT enumStruct = fdoExtension->PreAllocEnumStruct;
if (!(fdoExtension->FdoState & FDOS_STARTED)) {
Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return STATUS_DEVICE_NOT_READY; }
thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
switch (thisIrpSp->Parameters.QueryDeviceRelations.Type) { case BusRelations:
DebugPrint ((DBG_BUSSCAN, "IdeQueryDeviceRelations: bus relations\n"));
ASSERT(enumStruct); workItemContext = (PIDE_WORK_ITEM_CONTEXT) enumStruct->EnumWorkItemContext; ASSERT(workItemContext); ASSERT(workItemContext->WorkItem);
workItemContext->Irp = Irp;
#ifdef SYNC_DEVICE_RELATIONS
return ChannelQueryBusRelation ( DeviceObject, workItemContext);
#else
Irp->IoStatus.Status = STATUS_PENDING; IoMarkIrpPending(Irp);
IoQueueWorkItem( workItemContext->WorkItem, ChannelQueryBusRelation, DelayedWorkQueue, workItemContext );
return STATUS_PENDING; #endif //!SYNC_DEVICE_RELATIONS
break;
default: DebugPrint ((1, "IdeQueryDeviceRelations: Unsupported device relation\n"));
//
// Don't set the status if it is not success and is being passed
// down
//
//Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
break; }
IoSkipCurrentIrpStackLocation (Irp); return IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp); }
NTSTATUS ChannelQueryBusRelation ( IN PDEVICE_OBJECT DeviceObject, IN PIDE_WORK_ITEM_CONTEXT WorkItemContext ) {
PIRP irp; PFDO_EXTENSION fdoExtension; PIO_STACK_LOCATION thisIrpSp; PDEVICE_RELATIONS deviceRelations; LARGE_INTEGER tickCount; ULONG timeDiff;
irp = WorkItemContext->Irp;
//
// do not release resource for this worker item as they are pre-alloced
//
// IoFreeWorkItem(WorkItemContext->WorkItem);
//ExFreePool (WorkItemContext);
thisIrpSp = IoGetCurrentIrpStackLocation(irp); fdoExtension = thisIrpSp->DeviceObject->DeviceExtension;
LogBusScanStartTimer(&tickCount);
//
// grab the acpi/bios timing settings if any
// GTM should be called for every enumeration
//
DeviceQueryChannelTimingSettings ( fdoExtension, &fdoExtension->AcpiTimingSettings );
//
// Get parent's xfer mode interface
//
ChannelQueryTransferModeInterface ( fdoExtension );
//
// scan the bus
//
IdePortScanBus (fdoExtension);
timeDiff = LogBusScanStopTimer(&tickCount); LogBusScanTimeDiff(fdoExtension, L"IdeTotalBusScanTime", timeDiff);
#ifdef IDE_MEASURE_BUSSCAN_SPEED
if (timeDiff > 7000) {
DebugPrint ((DBG_WARNING, "WARNING: **************************************\n")); DebugPrint ((DBG_WARNING, "WARNING: IdePortScanBus 0x%x took %u millisec\n", fdoExtension->IdeResource.TranslatedCommandBaseAddress, timeDiff)); DebugPrint ((DBG_WARNING, "WARNING: **************************************\n"));
} else {
DebugPrint ((DBG_BUSSCAN, "IdePortScanBus 0x%x took %u millisec\n", fdoExtension->IdeResource.TranslatedCommandBaseAddress, timeDiff)); } #endif
deviceRelations = ChannelBuildDeviceRelationList ( fdoExtension );
irp->IoStatus.Information = (ULONG_PTR) deviceRelations; irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation (irp); return IoCallDriver (fdoExtension->AttacheeDeviceObject, irp); }
PDEVICE_RELATIONS ChannelBuildDeviceRelationList ( PFDO_EXTENSION FdoExtension ) { IDE_PATH_ID pathId; ULONG numPdoChildren; NTSTATUS status; PPDO_EXTENSION pdoExtension; ULONG deviceRelationsSize; PDEVICE_RELATIONS deviceRelations;
status = STATUS_SUCCESS;
pathId.l = 0; numPdoChildren = 0; while (pdoExtension = NextLogUnitExtensionWithTag( FdoExtension, &pathId, TRUE, ChannelBuildDeviceRelationList )) {
UnrefLogicalUnitExtensionWithTag ( FdoExtension, pdoExtension, ChannelBuildDeviceRelationList ); numPdoChildren++; }
if (numPdoChildren) { deviceRelationsSize = FIELD_OFFSET (DEVICE_RELATIONS, Objects) + numPdoChildren * sizeof(PDEVICE_OBJECT); } else { // Current build expect a DEVICE_RELATIONS with a Count of 0
// if we don't have any PDO to return
deviceRelationsSize = FIELD_OFFSET( DEVICE_RELATIONS, Objects ) + 1 * sizeof( PDEVICE_OBJECT ); }
deviceRelations = ExAllocatePool (NonPagedPool, deviceRelationsSize);
if(!deviceRelations) { DebugPrint ((DBG_ALWAYS, "ChannelBuildDeviceRelationList: Unable to allocate DeviceRelations structures\n")); status = STATUS_NO_MEMORY;
}
if (NT_SUCCESS(status)) {
(deviceRelations)->Count = 0;
pathId.l = 0; while ((deviceRelations->Count < numPdoChildren) && (pdoExtension = NextLogUnitExtensionWithTag( FdoExtension, &pathId, TRUE, ChannelBuildDeviceRelationList ))) {
KIRQL currentIrql; BOOLEAN deadMeat;
KeAcquireSpinLock(&pdoExtension->PdoSpinLock, ¤tIrql); deadMeat = pdoExtension->PdoState & PDOS_DEADMEAT ? TRUE : FALSE; KeReleaseSpinLock(&pdoExtension->PdoSpinLock, currentIrql);
if (!deadMeat) {
KeAcquireSpinLock(&pdoExtension->PdoSpinLock, ¤tIrql); SETMASK (pdoExtension->PdoState, PDOS_REPORTED_TO_PNP); KeReleaseSpinLock(&pdoExtension->PdoSpinLock, currentIrql);
deviceRelations->Objects[deviceRelations->Count] = pdoExtension->DeviceObject; ObReferenceObjectByPointer(deviceRelations->Objects[deviceRelations->Count], 0, 0, KernelMode); deviceRelations->Count++;
} else {
KeAcquireSpinLock(&pdoExtension->PdoSpinLock, ¤tIrql); CLRMASK (pdoExtension->PdoState, PDOS_REPORTED_TO_PNP); KeReleaseSpinLock(&pdoExtension->PdoSpinLock, currentIrql);
DebugPrint ((DBG_BUSSCAN, "0x%x target 0x%x pdoExtension 0x%x is marked DEADMEAT\n", pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress, pdoExtension->TargetId, pdoExtension)); }
UnrefLogicalUnitExtensionWithTag ( FdoExtension, pdoExtension, ChannelBuildDeviceRelationList ); }
DebugPrint ((DBG_BUSSCAN, "ChannelBuildDeviceRelationList: returning %d children\n", deviceRelations->Count)); }
return deviceRelations; }
NTSTATUS ChannelQueryId ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PIO_STACK_LOCATION thisIrpSp; PFDO_EXTENSION fdoExtension; NTSTATUS status; PWCHAR returnString; ANSI_STRING ansiString; UNICODE_STRING unicodeString;
PAGED_CODE();
thisIrpSp = IoGetCurrentIrpStackLocation( Irp ); fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension;
if (!(fdoExtension->FdoState & FDOS_STARTED)) {
Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return STATUS_DEVICE_NOT_READY; }
unicodeString.Buffer = NULL; switch (thisIrpSp->Parameters.QueryId.IdType) {
case BusQueryCompatibleIDs: case BusQueryHardwareIDs:
unicodeString.Length = 0; unicodeString.MaximumLength = 50 * sizeof(WCHAR); unicodeString.Buffer = ExAllocatePool(PagedPool, unicodeString.MaximumLength);
//
// Caller wants the unique id of the device
//
RtlInitAnsiString ( &ansiString, "*PNP0600" ); break;
default: break; }
if (unicodeString.Buffer) {
RtlAnsiStringToUnicodeString( &unicodeString, &ansiString, FALSE );
//
// double null terminate it
//
unicodeString.Buffer[unicodeString.Length/sizeof(WCHAR) + 0] = L'\0'; unicodeString.Buffer[unicodeString.Length/sizeof(WCHAR) + 1] = L'\0';
IoMarkIrpPending(Irp);
//
// we need to check if the lower driver handles this irp
// registry a completion routine. we can check
// when the irp comes back
//
IoCopyCurrentIrpStackLocationToNext (Irp);
IoSetCompletionRoutine( Irp, ChannelQueryIdCompletionRoutine, unicodeString.Buffer, TRUE, TRUE, TRUE );
} else {
//
// we don't care much about this irp
//
IoSkipCurrentIrpStackLocation (Irp); }
status = IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
if (unicodeString.Buffer) {
return STATUS_PENDING;
} else {
return status; } }
NTSTATUS ChannelQueryIdCompletionRoutine ( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ) { if (Irp->IoStatus.Status == STATUS_NOT_SUPPORTED) {
//
// the lower level driver didn't handle the irp
// return the device text string we created early
//
Irp->IoStatus.Information = (ULONG_PTR) Context; Irp->IoStatus.Status = STATUS_SUCCESS; } else {
//
// the lower driver handled the irp,
// we don't need to return our device text string
//
ExFreePool (Context); }
return Irp->IoStatus.Status; }
NTSTATUS ChannelUsageNotification ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PFDO_EXTENSION fdoExtension; PIO_STACK_LOCATION irpSp; PULONG deviceUsageCount;
ASSERT (DeviceObject); ASSERT (Irp);
fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension; ASSERT (fdoExtension);
if (!(fdoExtension->FdoState & FDOS_STARTED)) {
Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return STATUS_DEVICE_NOT_READY; }
irpSp = IoGetCurrentIrpStackLocation(Irp);
if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypePaging) {
//
// Adjust the paging path count for this device.
//
deviceUsageCount = &fdoExtension->PagingPathCount;
} else if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeHibernation) {
//
// Adjust the paging path count for this device.
//
deviceUsageCount = &fdoExtension->HiberPathCount;
} else if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeDumpFile) {
//
// Adjust the paging path count for this device.
//
deviceUsageCount = &fdoExtension->CrashDumpPathCount;
} else {
deviceUsageCount = NULL; DebugPrint ((DBG_ALWAYS, "ATAPI: Unknown IRP_MN_DEVICE_USAGE_NOTIFICATION type: 0x%x\n", irpSp->Parameters.UsageNotification.Type)); }
IoCopyCurrentIrpStackLocationToNext (Irp);
IoSetCompletionRoutine ( Irp, ChannelUsageNotificationCompletionRoutine, deviceUsageCount, TRUE, TRUE, TRUE);
ASSERT(fdoExtension->AttacheeDeviceObject); return IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
} // ChannelPagingNotification
NTSTATUS ChannelUsageNotificationCompletionRoutine ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { PFDO_EXTENSION fdoExtension; PULONG deviceUsageCount = Context;
fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension; ASSERT (fdoExtension);
if (NT_SUCCESS(Irp->IoStatus.Status)) {
if (deviceUsageCount) {
IoAdjustPagingPathCount ( deviceUsageCount, IoGetCurrentIrpStackLocation(Irp)->Parameters.UsageNotification.InPath ); } }
return Irp->IoStatus.Status; }
NTSTATUS ChannelDeviceIoControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIO_STACK_LOCATION thisIrpSp = IoGetCurrentIrpStackLocation(Irp); PFDO_EXTENSION fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension; PSTORAGE_PROPERTY_QUERY storageQuery; STORAGE_ADAPTER_DESCRIPTOR adapterDescriptor; ULONG outBufferSize; NTSTATUS status;
// pass it down if not supported and it is for the FDO stack
switch (thisIrpSp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_STORAGE_QUERY_PROPERTY:
storageQuery = Irp->AssociatedIrp.SystemBuffer;
if (thisIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(STORAGE_PROPERTY_QUERY)) {
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
} else {
if (storageQuery->PropertyId == StorageAdapterProperty) { // device property
switch (storageQuery->QueryType) { case PropertyStandardQuery: DebugPrint ((1, "IdePortPdoDispatch: IOCTL_STORAGE_QUERY_PROPERTY PropertyStandardQuery\n"));
RtlZeroMemory (&adapterDescriptor, sizeof(adapterDescriptor));
//
// BuildAtaDeviceDescriptor
//
adapterDescriptor.Version = sizeof (STORAGE_ADAPTER_DESCRIPTOR); adapterDescriptor.Size = sizeof (STORAGE_ADAPTER_DESCRIPTOR); adapterDescriptor.MaximumTransferLength = MAX_TRANSFER_SIZE_PER_SRB; adapterDescriptor.MaximumPhysicalPages = SP_UNINITIALIZED_VALUE; adapterDescriptor.AlignmentMask = DeviceObject->AlignmentRequirement; adapterDescriptor.AdapterUsesPio = TRUE; // We always support PIO
adapterDescriptor.AdapterScansDown = FALSE; adapterDescriptor.CommandQueueing = FALSE; adapterDescriptor.AcceleratedTransfer = FALSE; adapterDescriptor.BusType = BusTypeAta; // Bus type should be ATA
adapterDescriptor.BusMajorVersion = 1; // Major version
adapterDescriptor.BusMinorVersion = 0; //
if (thisIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_ADAPTER_DESCRIPTOR)) {
outBufferSize = thisIrpSp->Parameters.DeviceIoControl.OutputBufferLength; } else {
outBufferSize = sizeof(STORAGE_ADAPTER_DESCRIPTOR); }
RtlCopyMemory (Irp->AssociatedIrp.SystemBuffer, &adapterDescriptor, outBufferSize); Irp->IoStatus.Information = outBufferSize; Irp->IoStatus.Status = STATUS_SUCCESS; break;
case PropertyExistsQuery: DebugPrint ((1, "IdePortPdoDispatch: IOCTL_STORAGE_QUERY_PROPERTY PropertyExistsQuery\n")); Irp->IoStatus.Status = STATUS_SUCCESS; break;
case PropertyMaskQuery: DebugPrint ((1, "IdePortPdoDispatch: IOCTL_STORAGE_QUERY_PROPERTY PropertyMaskQuery\n")); Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; break;
default: DebugPrint ((1, "IdePortPdoDispatch: IOCTL_STORAGE_QUERY_PROPERTY unknown type\n")); Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; break; } } } break;
default:
//
// we don't know what this deviceIoControl Irp is
//
if (thisIrpSp->DeviceObject == DeviceObject) {
//
// this irp could come from the PDO stack
//
// forward this unknown request if and only
// if this irp is for the FDO stack
//
IoSkipCurrentIrpStackLocation (Irp); return IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp); break; } Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; break;
}
status = Irp->IoStatus.Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; }
VOID ChannelQueryBusMasterInterface ( PFDO_EXTENSION FdoExtension ) { IO_STACK_LOCATION irpSp; NTSTATUS status;
FdoExtension->BoundWithBmParent = FALSE;
RtlZeroMemory (&irpSp, sizeof(irpSp));
irpSp.Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_PCIIDE_BUSMASTER_INTERFACE; irpSp.Parameters.QueryInterface.Version = 1; irpSp.Parameters.QueryInterface.Size = sizeof (FdoExtension->HwDeviceExtension->BusMasterInterface); irpSp.Parameters.QueryInterface.Interface = (PINTERFACE) &FdoExtension->HwDeviceExtension->BusMasterInterface; irpSp.Parameters.QueryInterface.InterfaceSpecificData = NULL;
irpSp.MajorFunction = IRP_MJ_PNP; irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE;
status = IdePortSyncSendIrp (FdoExtension->AttacheeDeviceObject, &irpSp, NULL); if (NT_SUCCESS(status)) { FdoExtension->BoundWithBmParent = TRUE; } return; }
#ifdef ENABLE_NATIVE_MODE
VOID ChannelQueryInterruptInterface ( PFDO_EXTENSION FdoExtension ) { IO_STACK_LOCATION irpSp; NTSTATUS status;
RtlZeroMemory (&irpSp, sizeof(irpSp));
irpSp.Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_PCIIDE_INTERRUPT_INTERFACE; irpSp.Parameters.QueryInterface.Version = 1; irpSp.Parameters.QueryInterface.Size = sizeof (FdoExtension->InterruptInterface); irpSp.Parameters.QueryInterface.Interface = (PINTERFACE) &FdoExtension->InterruptInterface; irpSp.Parameters.QueryInterface.InterfaceSpecificData = NULL;
irpSp.MajorFunction = IRP_MJ_PNP; irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE;
DebugPrint((1, "Querying interrupt interface for Fdoe 0x%x\n", FdoExtension));
status = IdePortSyncSendIrp (FdoExtension->AttacheeDeviceObject, &irpSp, NULL);
return; } #endif
VOID ChannelQueryTransferModeInterface ( PFDO_EXTENSION FdoExtension ) { IO_STACK_LOCATION irpSp; NTSTATUS status; ULONG i;
PAGED_CODE();
RtlZeroMemory (&irpSp, sizeof(irpSp));
irpSp.Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_PCIIDE_XFER_MODE_INTERFACE; irpSp.Parameters.QueryInterface.Version = 1; irpSp.Parameters.QueryInterface.Size = sizeof (FdoExtension->TransferModeInterface); irpSp.Parameters.QueryInterface.Interface = (PINTERFACE) &FdoExtension->TransferModeInterface; irpSp.Parameters.QueryInterface.InterfaceSpecificData = NULL;
irpSp.MajorFunction = IRP_MJ_PNP; irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE;
status = IdePortSyncSendIrp (FdoExtension->AttacheeDeviceObject, &irpSp, NULL); if (NT_SUCCESS(status)) { if (FdoExtension->TransferModeInterface.SupportLevel != PciIdeFullXferModeSupport) {
//
// We got the sfer mode interface from our parent,
// but it has only the basic functionality. It
// just relies on the BIOS to program its timing
// registers during POST. It doesn't really know
// how to program its timing registers.
//
for (i=0; i<MAX_IDE_DEVICE; i++) { if (FdoExtension->AcpiTimingSettings.Speed[i].Pio != ACPI_XFER_MODE_NOT_SUPPORT) { //
// looks like ACPI is present and it knows how to program
// ide timing registers. Let's forget our parent xfer mode
// interface and go with the ACPI xfer mode interface
//
status = STATUS_UNSUCCESSFUL; } } }
ASSERT (FdoExtension->TransferModeInterface.TransferModeTimingTable); } #ifdef ALWAYS_USE_APCI_IF_AVAILABLE
for (i=0; i<MAX_IDE_DEVICE; i++) {
if (FdoExtension->AcpiTimingSettings.Speed[i].Pio != ACPI_XFER_MODE_NOT_SUPPORT) { status = STATUS_UNSUCCESSFUL; } } #endif // ALWAYS_USE_APCI_IF_AVAILABLE
if (!NT_SUCCESS(status)) {
PULONG transferModeTimingTable = FdoExtension->TransferModeInterface.TransferModeTimingTable; //
// if we can't get the TransferModeInterface,
// we will default to the ACPI TransferModeInterface
//
if ((FdoExtension->AcpiTimingSettings.Speed[0].Pio != ACPI_XFER_MODE_NOT_SUPPORT) || (FdoExtension->AcpiTimingSettings.Speed[1].Pio != ACPI_XFER_MODE_NOT_SUPPORT)) {
FdoExtension->TransferModeInterface.SupportLevel = PciIdeFullXferModeSupport;
} else {
FdoExtension->TransferModeInterface.SupportLevel = PciIdeBasicXferModeSupport; } FdoExtension->TransferModeInterface.Context = FdoExtension; FdoExtension->TransferModeInterface.TransferModeSelect = ChannelAcpiTransferModeSelect;
//
// Fill up the timingTable with the default cycle times.
//
if (transferModeTimingTable == NULL) { FdoExtension->TransferModeInterface.TransferModeTimingTable = FdoExtension-> DefaultTransferModeTimingTable; FdoExtension->TransferModeInterface.TransferModeTableLength = MAX_XFER_MODE; } }
if (FdoExtension->TransferModeInterface.SupportLevel == PciIdeBasicXferModeSupport) {
//
// we don't really have code to set the correct
// xfer mode timing on the controller.
// our TransferModeInterface is really picking
// whatever mode set by the bios. and since there
// is no way to figure what the current PIO mode
// the drive is in, we are setting a flag in
// the HwDeviceExtension so that we won't try
// to change the pio transfer mode
//
FdoExtension->HwDeviceExtension->NoPioSetTransferMode = TRUE; }
ASSERT (FdoExtension->TransferModeInterface.TransferModeSelect); ASSERT (FdoExtension->TransferModeInterface.TransferModeTimingTable);
return; }
VOID ChannelUnbindBusMasterParent ( PFDO_EXTENSION FdoExtension ) { // ISSUE: 08/30/2000 implement me!!!
return; }
VOID ChannelQuerySyncAccessInterface ( PFDO_EXTENSION FdoExtension ) { IO_STACK_LOCATION irpSp; NTSTATUS status;
RtlZeroMemory (&irpSp, sizeof(irpSp)); RtlZeroMemory ( &FdoExtension->SyncAccessInterface, sizeof (FdoExtension->SyncAccessInterface) );
irpSp.Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_PCIIDE_SYNC_ACCESS_INTERFACE; irpSp.Parameters.QueryInterface.Version = 1; irpSp.Parameters.QueryInterface.Size = sizeof (FdoExtension->SyncAccessInterface); irpSp.Parameters.QueryInterface.Interface = (PINTERFACE) &FdoExtension->SyncAccessInterface; irpSp.Parameters.QueryInterface.InterfaceSpecificData = NULL;
irpSp.MajorFunction = IRP_MJ_PNP; irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE;
status = IdePortSyncSendIrp (FdoExtension->AttacheeDeviceObject, &irpSp, NULL);
//
// parent doesn't support access token,
//
if (!NT_SUCCESS(status)) {
FdoExtension->SyncAccessInterface.AllocateAccessToken = 0; FdoExtension->SyncAccessInterface.Token = 0; }
return; }
VOID ChannelQueryRequestProperResourceInterface ( PFDO_EXTENSION FdoExtension ) { IO_STACK_LOCATION irpSp; NTSTATUS status;
RtlZeroMemory (&irpSp, sizeof(irpSp)); RtlZeroMemory ( &FdoExtension->RequestProperResourceInterface, sizeof (FdoExtension->RequestProperResourceInterface) );
irpSp.Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_PCIIDE_REQUEST_PROPER_RESOURCES; irpSp.Parameters.QueryInterface.Version = 1; irpSp.Parameters.QueryInterface.Size = sizeof (FdoExtension->RequestProperResourceInterface); irpSp.Parameters.QueryInterface.Interface = (PINTERFACE) &FdoExtension->RequestProperResourceInterface; irpSp.Parameters.QueryInterface.InterfaceSpecificData = NULL;
irpSp.MajorFunction = IRP_MJ_PNP; irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE;
status = IdePortSyncSendIrp (FdoExtension->AttacheeDeviceObject, &irpSp, NULL); return; }
__inline VOID ChannelEnableInterrupt ( IN PFDO_EXTENSION FdoExtension ) { ULONG i;
for (i=0; i<(FdoExtension->HwDeviceExtension->MaxIdeDevice/MAX_IDE_DEVICE);i++) {
SelectIdeLine(&FdoExtension->HwDeviceExtension->BaseIoAddress1,i);
IdePortOutPortByte ( FdoExtension->HwDeviceExtension->BaseIoAddress2.DeviceControl, IDE_DC_REENABLE_CONTROLLER ); } }
__inline VOID ChannelDisableInterrupt ( IN PFDO_EXTENSION FdoExtension ) { ULONG i;
for (i=0; i<(FdoExtension->HwDeviceExtension->MaxIdeDevice/MAX_IDE_DEVICE);i++) {
SelectIdeLine(&FdoExtension->HwDeviceExtension->BaseIoAddress1,i);
IdePortOutPortByte ( FdoExtension->HwDeviceExtension->BaseIoAddress2.DeviceControl, IDE_DC_DISABLE_INTERRUPTS ); } }
NTSTATUS ChannelAcpiTransferModeSelect ( IN PVOID Context, PPCIIDE_TRANSFER_MODE_SELECT XferMode ) { PFDO_EXTENSION fdoExtension = Context; ULONG i; BOOLEAN useUdmaMode[MAX_IDE_DEVICE]; BOOLEAN dmaMode; PIDENTIFY_DATA ataIdentifyData[MAX_IDE_DEVICE]; NTSTATUS status; ULONG numDevices; ULONG timingMode[MAX_IDE_DEVICE]; ULONG cycleTime[MAX_IDE_DEVICE]; ULONG dmaTiming; PACPI_IDE_TIMING acpiTimingSettings; ACPI_IDE_TIMING newAcpiTimingSettings; PULONG transferModeTimingTable=XferMode->TransferModeTimingTable;
ASSERT(transferModeTimingTable);
ASSERT (IsNEC_98 == FALSE);
if (fdoExtension->DeviceChanged) { DebugPrint((DBG_XFERMODE, "Updating boot acpi timing settings\n")); RtlCopyMemory (&fdoExtension->BootAcpiTimingSettings, &fdoExtension->AcpiTimingSettings, sizeof(newAcpiTimingSettings) ); } acpiTimingSettings = &fdoExtension->BootAcpiTimingSettings;
RtlZeroMemory (&newAcpiTimingSettings, sizeof(newAcpiTimingSettings)); newAcpiTimingSettings.Flags.b.IndependentTiming = acpiTimingSettings->Flags.b.IndependentTiming;
//
// how many devices do we have?
//
for (i=numDevices=0; i<MAX_IDE_DEVICE; i++) { if (XferMode->DevicePresent[i]) { numDevices++; } } ASSERT (numDevices);
//
// pick the device pio timing
//
for (i=0; i<MAX_IDE_DEVICE; i++) { ULONG mode;
if (!XferMode->DevicePresent[i]) { continue; }
GetHighestPIOTransferMode(XferMode->DeviceTransferModeSupported[i], mode);
timingMode[i] = 1<<mode; cycleTime[i] = XferMode->BestPioCycleTime[i]; }
if ((numDevices > 1) && !acpiTimingSettings->Flags.b.IndependentTiming) {
//
// pick the slower of the two timings
// (the smaller timing mode value, the slower it is)
//
if (timingMode[0] < timingMode[1]) {
cycleTime[1] = cycleTime[0]; timingMode[1] = timingMode[0];
} else {
cycleTime[0] = cycleTime[1]; timingMode[0] = timingMode[1]; } }
//
// store the pio mode selected
//
for (i=0; i<MAX_IDE_DEVICE; i++) {
if (XferMode->DevicePresent[i]) { XferMode->DeviceTransferModeSelected[i] = timingMode[i]; newAcpiTimingSettings.Speed[i].Pio = cycleTime[i];
if (i == 0) { newAcpiTimingSettings.Flags.b.IoChannelReady0 = XferMode->IoReadySupported[i]; } else { newAcpiTimingSettings.Flags.b.IoChannelReady1 = XferMode->IoReadySupported[i]; }
} else { XferMode->DeviceTransferModeSelected[i] = 0; } }
//
// pick the device dma timing
//
for (i=0; i<MAX_IDE_DEVICE; i++) {
ULONG mode; BOOLEAN useDma = TRUE;
timingMode[i] = 0; cycleTime[i]= ACPI_XFER_MODE_NOT_SUPPORT;
if (!XferMode->DevicePresent[i]) { continue; }
//
// check the acpi flag for ultra dma
//
if (i == 0) {
useUdmaMode[i] = acpiTimingSettings->Flags.b.UltraDma0 ? TRUE: FALSE;
} else {
ASSERT (i==1); useUdmaMode[i] = acpiTimingSettings->Flags.b.UltraDma1 ? TRUE: FALSE; }
//
// get the dma timing specified in _GTM
//
dmaTiming = acpiTimingSettings->Speed[i].Dma;
//
// if dma is not supported, don't do anything, We have already set the PIO mode.
//
if (dmaTiming == ACPI_XFER_MODE_NOT_SUPPORT) { useUdmaMode[i]=0; useDma = FALSE; mode = PIO0; }
//
// Find the highest UDMA mode
//
if (useUdmaMode[i]) {
GetHighestDMATransferMode(XferMode->DeviceTransferModeSupported[i], mode);
while (mode>= UDMA0) { if ((dmaTiming <= transferModeTimingTable[mode]) && (XferMode->DeviceTransferModeSupported[i] & (1<<mode))) {
timingMode[i] = 1<<mode; cycleTime[i] = transferModeTimingTable[mode]; ASSERT(cycleTime[i]);
// we got a udma mode. so don't try to find a dma mode.
useDma = FALSE; break; } mode--; }
}
//
// highest DMA mode
// useDma is false only when either dma is not supported or an udma mode is
// already selected.
//
if (useDma) {
ULONG tempMode;
// we shouldn't be using UDMA now.
// this will set the flags for STM correctly.
useUdmaMode[i]=FALSE;
// mask out UDMA and MWDMA0
tempMode = XferMode-> DeviceTransferModeSupported[i] & (SWDMA_SUPPORT | MWDMA_SUPPORT); tempMode &= (~MWDMA_MODE0);
GetHighestDMATransferMode(tempMode, mode);
if (mode >= MWDMA1) { timingMode[i] = 1<<mode; cycleTime[i] = XferMode->BestMwDmaCycleTime[i]; ASSERT(cycleTime[i]); } else if (mode == SWDMA2) { timingMode[i] = 1<<mode; cycleTime[i] = XferMode->BestSwDmaCycleTime[i]; ASSERT(cycleTime[i]); } // else don't do anything. PIO is already set
}
}
if ((numDevices > 1) && !acpiTimingSettings->Flags.b.IndependentTiming) {
//
// pick the slower of the two timings
// (the smaller timing mode value, the slower it is)
//
if (timingMode[0] < timingMode[1]) {
cycleTime[1] = cycleTime[0]; timingMode[1] = timingMode[0];
} else {
cycleTime[0] = cycleTime[1]; timingMode[0] = timingMode[1]; }
//
// both dma mode have to be the same
//
if (useUdmaMode[0] != useUdmaMode[1]) { useUdmaMode[0] = 0; useUdmaMode[1] = 0; } }
//
// store the dma mode selected
//
for (i=0; i<MAX_IDE_DEVICE; i++) {
if (XferMode->DevicePresent[i]) {
XferMode->DeviceTransferModeSelected[i] |= timingMode[i]; newAcpiTimingSettings.Speed[i].Dma = cycleTime[i];
if (i==0) { newAcpiTimingSettings.Flags.b.UltraDma0 = useUdmaMode[i]; } else { newAcpiTimingSettings.Flags.b.UltraDma1 = useUdmaMode[i]; } } }
if (fdoExtension->DmaDetectionLevel == DdlPioOnly) {
//
// remove all DMA modes
//
for (i=0; i<MAX_IDE_DEVICE; i++) {
XferMode->DeviceTransferModeSelected[i] &= PIO_SUPPORT; } }
if ((acpiTimingSettings->Speed[0].Pio != ACPI_XFER_MODE_NOT_SUPPORT) || (acpiTimingSettings->Speed[1].Pio != ACPI_XFER_MODE_NOT_SUPPORT)) {
//
// looks like we are on an ACPI machine and
// it supports IDE timing control method (_STM)
//
for (i=0; i<MAX_IDE_DEVICE; i++) { if (XferMode->DevicePresent[i]) { ataIdentifyData[i] = fdoExtension->HwDeviceExtension->IdentifyData + i; } else { ataIdentifyData[i] = NULL; } } //
// save the new timing settings
//
RtlCopyMemory ( &fdoExtension->AcpiTimingSettings, &newAcpiTimingSettings, sizeof(newAcpiTimingSettings));
//
// call ACPI to program the timing registers
//
status = ChannelSyncSetACPITimingSettings ( fdoExtension, &newAcpiTimingSettings, ataIdentifyData ); } else {
//
// legacy controller
//
for (i=0; i<MAX_IDE_DEVICE; i++) { XferMode->DeviceTransferModeSelected[i] &= PIO_SUPPORT; }
status = STATUS_SUCCESS; }
return status; }
NTSTATUS ChannelRestoreTiming ( IN PFDO_EXTENSION FdoExtension, IN PSET_ACPI_TIMING_COMPLETION_ROUTINE CallerCompletionRoutine, IN PVOID CallerContext ) { ULONG i; PIDENTIFY_DATA ataIdentifyData[MAX_IDE_DEVICE]; NTSTATUS status;
PACPI_IDE_TIMING acpiTimingSettings;
acpiTimingSettings = &FdoExtension->AcpiTimingSettings;
if (FdoExtension->NumberOfLogicalUnits && ((acpiTimingSettings->Speed[0].Pio != ACPI_XFER_MODE_NOT_SUPPORT) || (acpiTimingSettings->Speed[1].Pio != ACPI_XFER_MODE_NOT_SUPPORT))) {
//
// looks like we are on an ACPI machine and
// it supports IDE timing control method (_STM)
//
for (i=0; i<MAX_IDE_DEVICE; i++) { if (FdoExtension->HwDeviceExtension->DeviceFlags[i] & DFLAGS_DEVICE_PRESENT) { ataIdentifyData[i] = FdoExtension->HwDeviceExtension->IdentifyData + i; } else { ataIdentifyData[i] = NULL; } } //
// call ACPI to program the timing registers
//
status = ChannelSetACPITimingSettings ( FdoExtension, acpiTimingSettings, ataIdentifyData, CallerCompletionRoutine, CallerContext );
} else {
//
// non-acpi controller
//
if (FdoExtension->NumberOfLogicalUnits) { AtapiSyncSelectTransferMode ( FdoExtension, FdoExtension->HwDeviceExtension, FdoExtension->TimingModeAllowed ); } (*CallerCompletionRoutine) ( FdoExtension->DeviceObject, STATUS_SUCCESS, CallerContext ); status = STATUS_SUCCESS; }
return status; }
NTSTATUS ChannelRestoreTimingCompletionRoutine ( IN PDEVICE_OBJECT DeviceObject, IN NTSTATUS Status, IN PVOID Context ) { PIO_STACK_LOCATION thisIrpSp; PFDO_POWER_CONTEXT context = Context; PIRP originalPowerIrp;
context->TimingRestored = TRUE;
originalPowerIrp = context->OriginalPowerIrp; originalPowerIrp->IoStatus.Status = Status;
thisIrpSp = IoGetCurrentIrpStackLocation(originalPowerIrp);
//
// finish off the original power irp
//
FdoPowerCompletionRoutine ( thisIrpSp->DeviceObject, originalPowerIrp, Context );
//
// continue with the irp completion
//
IoCompleteRequest (originalPowerIrp, IO_NO_INCREMENT);
return Status; }
NTSTATUS ChannelFilterResourceRequirements ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { NTSTATUS status; PFDO_EXTENSION fdoExtension; ULONG i, j, k; IO_STACK_LOCATION irpSp; PCIIDE_XFER_MODE_INTERFACE xferModeInterface;
PIO_RESOURCE_REQUIREMENTS_LIST requirementsListIn; PIO_RESOURCE_LIST resourceListIn; PIO_RESOURCE_DESCRIPTOR resourceDescriptorIn;
PIO_RESOURCE_DESCRIPTOR cmdRegResourceDescriptor; PIO_RESOURCE_DESCRIPTOR ctrlRegResourceDescriptor; PIO_RESOURCE_DESCRIPTOR intRegResourceDescriptor; PIO_RESOURCE_REQUIREMENTS_LIST requirementsListOut; ULONG requirementsListSizeOut; PIO_RESOURCE_LIST resourceListOut; PIO_RESOURCE_DESCRIPTOR resourceDescriptorOut;
PAGED_CODE(); //
// the value will stay NULL if no filtering required
//
requirementsListOut = NULL;
#ifdef IDE_FILTER_PROMISE_TECH_RESOURCES
if (NT_SUCCESS(ChannelFilterPromiseTechResourceRequirements (DeviceObject, Irp))) { goto getout; } #endif // IDE_FILTER_PROMISE_TECH_RESOURCES
//
// do a simple test to check if we have a pciidex parent
//
RtlZeroMemory (&irpSp, sizeof(irpSp));
irpSp.Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_PCIIDE_XFER_MODE_INTERFACE; irpSp.Parameters.QueryInterface.Version = 1; irpSp.Parameters.QueryInterface.Size = sizeof (xferModeInterface); irpSp.Parameters.QueryInterface.Interface = (PINTERFACE) &xferModeInterface; irpSp.Parameters.QueryInterface.InterfaceSpecificData = NULL; irpSp.MajorFunction = IRP_MJ_PNP; irpSp.MinorFunction = IRP_MN_QUERY_INTERFACE;
fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension; status = IdePortSyncSendIrp (fdoExtension->AttacheeDeviceObject, &irpSp, NULL);
if (NT_SUCCESS(status)) {
//
// we have a pciidex as a parent. it would
// take care of the resource requirement
// no need to filter
//
goto getout; }
if (NT_SUCCESS(Irp->IoStatus.Status)) {
ASSERT (Irp->IoStatus.Information); requirementsListIn = (PIO_RESOURCE_REQUIREMENTS_LIST) Irp->IoStatus.Information;
} else {
PIO_STACK_LOCATION thisIrpSp;
thisIrpSp = IoGetCurrentIrpStackLocation(Irp); requirementsListIn = thisIrpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList; }
if (requirementsListIn == NULL) { goto getout; }
if (requirementsListIn->AlternativeLists == 0) { goto getout; } requirementsListSizeOut = requirementsListIn->ListSize + requirementsListIn->AlternativeLists * sizeof(IO_RESOURCE_DESCRIPTOR);
requirementsListOut = ExAllocatePool (PagedPool, requirementsListSizeOut); if (requirementsListOut == NULL) { goto getout; }
*requirementsListOut = *requirementsListIn; requirementsListOut->ListSize = requirementsListSizeOut;
//
// some init.
//
resourceListIn = requirementsListIn->List; resourceListOut = requirementsListOut->List; for (j=0; j<requirementsListIn->AlternativeLists; j++) {
resourceDescriptorIn = resourceListIn->Descriptors; //
// analyze what resources we are getting
//
cmdRegResourceDescriptor = NULL; ctrlRegResourceDescriptor = NULL; intRegResourceDescriptor = NULL; for (i=0; i<resourceListIn->Count; i++) { switch (resourceDescriptorIn[i].Type) { case CmResourceTypePort: { if ((resourceDescriptorIn[i].u.Port.Length == 8) && (cmdRegResourceDescriptor == NULL)) { cmdRegResourceDescriptor = resourceDescriptorIn + i; } else if (((resourceDescriptorIn[i].u.Port.Length == 1) || (resourceDescriptorIn[i].u.Port.Length == 2) || (resourceDescriptorIn[i].u.Port.Length == 4)) && (ctrlRegResourceDescriptor == NULL)) { ctrlRegResourceDescriptor = resourceDescriptorIn + i; } else if ((resourceDescriptorIn[i].u.Port.Length >= 0x10) && (cmdRegResourceDescriptor == NULL) && (ctrlRegResourceDescriptor == NULL)) { //
// probably pcmcia device. it likes to combine
// both io ranges into 1.
//
cmdRegResourceDescriptor = resourceDescriptorIn + i; ctrlRegResourceDescriptor = resourceDescriptorIn + i; } } break; case CmResourceTypeInterrupt: { if (intRegResourceDescriptor == NULL) { intRegResourceDescriptor = resourceDescriptorIn + i; } } break; default: break; } } //
// making a new copy
//
*resourceListOut = *resourceListIn; //
// figure out what is missing
//
if (cmdRegResourceDescriptor && ((cmdRegResourceDescriptor->u.Port.MaximumAddress.QuadPart - cmdRegResourceDescriptor->u.Port.MinimumAddress.QuadPart + 1) == 8) && (ctrlRegResourceDescriptor == NULL)) { //
// missing controller register resource descriptor.
//
resourceDescriptorOut = resourceListOut->Descriptors; for (i=0; i<resourceListOut->Count; i++) { *resourceDescriptorOut = resourceDescriptorIn[i]; resourceDescriptorOut++; if ((resourceDescriptorIn + i) == cmdRegResourceDescriptor) { //
// add the control register resource
//
*resourceDescriptorOut = resourceDescriptorIn[i]; resourceDescriptorOut->u.Port.Length = 1; resourceDescriptorOut->u.Port.Alignment = 1; resourceDescriptorOut->u.Port.MinimumAddress.QuadPart = resourceDescriptorOut->u.Port.MaximumAddress.QuadPart = cmdRegResourceDescriptor->u.Port.MinimumAddress.QuadPart + 0x206; resourceDescriptorOut++; } } //
// account for the new control register resource
//
resourceListOut->Count++; } else { resourceDescriptorOut = resourceListOut->Descriptors; k = resourceListOut->Count; for (i = 0; i < k; i++) {
if (IsNEC_98) { //
// NEC98 DevNode includes the ide rom memory resource.
// But it should be gotten by NTDETECT.COM&HAL.DLL, so ignore it here.
//
if ((resourceDescriptorIn[i].Type == CmResourceTypeMemory) && (resourceDescriptorIn[i].u.Memory.MinimumAddress.QuadPart == 0xd8000) && (resourceDescriptorIn[i].u.Memory.Length == 0x4000)) {
resourceListOut->Count--; continue; } } *resourceDescriptorOut = resourceDescriptorIn[i]; resourceDescriptorOut++; } } resourceListIn = (PIO_RESOURCE_LIST) (resourceDescriptorIn + resourceListIn->Count); resourceListOut = (PIO_RESOURCE_LIST) resourceDescriptorOut; }
getout: if (requirementsListOut) {
if (NT_SUCCESS(Irp->IoStatus.Status)) {
ExFreePool ((PVOID) Irp->IoStatus.Information);
} else {
Irp->IoStatus.Status = STATUS_SUCCESS; } Irp->IoStatus.Information = (ULONG_PTR) requirementsListOut; }
return IdePortPassDownToNextDriver (DeviceObject, Irp); }
static PCWSTR PcmciaIdeChannelDeviceId = L"PCMCIA\\*PNP0600"; BOOLEAN ChannelQueryPcmciaParent ( PFDO_EXTENSION FdoExtension ) { BOOLEAN foundIt = FALSE; NTSTATUS status; IO_STATUS_BLOCK ioStatus; IO_STACK_LOCATION irpSp;
PAGED_CODE();
//
// do a simple test to check if we have a pciidex parent
//
RtlZeroMemory (&irpSp, sizeof(irpSp));
irpSp.Parameters.QueryId.IdType = BusQueryHardwareIDs; irpSp.MajorFunction = IRP_MJ_PNP; irpSp.MinorFunction = IRP_MN_QUERY_ID;
ioStatus.Status = STATUS_NOT_SUPPORTED; status = IdePortSyncSendIrp (FdoExtension->AttacheeDeviceObject, &irpSp, &ioStatus);
if (NT_SUCCESS(status)) {
PWSTR wstr; UNICODE_STRING hwId; UNICODE_STRING targetId; RtlInitUnicodeString( &targetId, PcmciaIdeChannelDeviceId); wstr = (PWSTR) ioStatus.Information; while (*wstr) { RtlInitUnicodeString(&hwId, wstr); if (!RtlCompareUnicodeString( &hwId, &targetId, FALSE)) { ExFreePool ((PVOID) ioStatus.Information); DebugPrint ((DBG_PNP, "ATAPI: pcmcia parent\n")); return TRUE; } wstr += hwId.Length / sizeof(WCHAR); wstr++; // NULL character
} ExFreePool ((PVOID) ioStatus.Information); } return FALSE; }
#ifdef IDE_FILTER_PROMISE_TECH_RESOURCES
static PCWSTR PromiseTechDeviceId[] = { L"ISAPNP\\BJB1000" }; #define NUM_PROMISE_TECH_ID (sizeof(PromiseTechDeviceId)/sizeof(PCWSTR))
NTSTATUS ChannelFilterPromiseTechResourceRequirements ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { BOOLEAN foundIt = FALSE; BOOLEAN firstIrq = FALSE; ULONG numExtraIoResDescriptor = 0; NTSTATUS status; IO_STATUS_BLOCK ioStatus; PFDO_EXTENSION fdoExtension; ULONG i, j, k; IO_STACK_LOCATION irpSp; PCIIDE_XFER_MODE_INTERFACE xferModeInterface;
PIO_RESOURCE_REQUIREMENTS_LIST requirementsListIn; PIO_RESOURCE_LIST resourceListIn; PIO_RESOURCE_DESCRIPTOR resourceDescriptorIn; PIO_RESOURCE_DESCRIPTOR brokenResourceDescriptor;
PIO_RESOURCE_DESCRIPTOR cmdRegResourceDescriptor; PIO_RESOURCE_DESCRIPTOR ctrlRegResourceDescriptor; PIO_RESOURCE_DESCRIPTOR intRegResourceDescriptor; PIO_RESOURCE_REQUIREMENTS_LIST requirementsListOut; ULONG requirementsListSizeOut; PIO_RESOURCE_LIST resourceListOut; PIO_RESOURCE_DESCRIPTOR resourceDescriptorOut;
PAGED_CODE();
//
// the value will stay NULL if no filtering required
//
requirementsListOut = NULL;
//
// do a simple test to check if we have a pciidex parent
//
RtlZeroMemory (&irpSp, sizeof(irpSp));
irpSp.Parameters.QueryId.IdType = BusQueryDeviceID; irpSp.MajorFunction = IRP_MJ_PNP; irpSp.MinorFunction = IRP_MN_QUERY_ID;
fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension; ioStatus.Status = STATUS_NOT_SUPPORTED; status = IdePortSyncSendIrp (fdoExtension->AttacheeDeviceObject, &irpSp, &ioStatus);
if (NT_SUCCESS(status)) {
UNICODE_STRING deviceId; UNICODE_STRING promiseTechDeviceId; RtlInitUnicodeString( &deviceId, (PCWSTR) ioStatus.Information); for (i=0; i<NUM_PROMISE_TECH_ID && !foundIt; i++) { RtlInitUnicodeString( &promiseTechDeviceId, PromiseTechDeviceId[i]); if (deviceId.Length >= promiseTechDeviceId.Length) { deviceId.Length = promiseTechDeviceId.Length; if (!RtlCompareUnicodeString( &promiseTechDeviceId, &deviceId, FALSE)) { foundIt = TRUE; } } } ExFreePool ((PVOID) ioStatus.Information); } if (!foundIt) { goto getout; }
if (NT_SUCCESS(Irp->IoStatus.Status)) {
ASSERT (Irp->IoStatus.Information); requirementsListIn = (PIO_RESOURCE_REQUIREMENTS_LIST) Irp->IoStatus.Information;
} else {
PIO_STACK_LOCATION thisIrpSp;
thisIrpSp = IoGetCurrentIrpStackLocation(Irp); requirementsListIn = thisIrpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList; }
if (requirementsListIn == NULL) { goto getout; }
if (requirementsListIn->AlternativeLists == 0) { goto getout; } //
// look for the bad resource descriptior
//
resourceListIn = requirementsListIn->List; brokenResourceDescriptor = NULL; for (j=0; j<requirementsListIn->AlternativeLists; j++) {
resourceDescriptorIn = resourceListIn->Descriptors; //
// analyze what resources we are getting
//
for (i=0; i<resourceListIn->Count; i++) { switch (resourceDescriptorIn[i].Type) { case CmResourceTypePort: { ULONG alignmentMask; alignmentMask = resourceDescriptorIn[i].u.Port.Alignment - 1; if (resourceDescriptorIn[i].u.Port.MinimumAddress.LowPart & alignmentMask) { //
// broken resource requirement;
//
brokenResourceDescriptor = resourceDescriptorIn + i; } } break; default: break; } } } if (brokenResourceDescriptor) { ULONG alignmentMask; PHYSICAL_ADDRESS minAddress; PHYSICAL_ADDRESS addressRange; alignmentMask = brokenResourceDescriptor->u.Port.Alignment - 1; alignmentMask = ~alignmentMask; minAddress = brokenResourceDescriptor->u.Port.MinimumAddress; minAddress.LowPart &= alignmentMask; addressRange.QuadPart = (brokenResourceDescriptor->u.Port.MaximumAddress.QuadPart - minAddress.QuadPart); numExtraIoResDescriptor = (ULONG) (addressRange.QuadPart / brokenResourceDescriptor->u.Port.Alignment); } requirementsListSizeOut = requirementsListIn->ListSize + numExtraIoResDescriptor * sizeof(IO_RESOURCE_DESCRIPTOR);
requirementsListOut = ExAllocatePool (PagedPool, requirementsListSizeOut); if (requirementsListOut == NULL) { goto getout; }
*requirementsListOut = *requirementsListIn; requirementsListOut->ListSize = requirementsListSizeOut;
//
// some init.
//
resourceListIn = requirementsListIn->List; resourceListOut = requirementsListOut->List; for (j=0; j<requirementsListIn->AlternativeLists; j++) {
resourceDescriptorIn = resourceListIn->Descriptors; //
// making a new copy
//
*resourceListOut = *resourceListIn; resourceListOut->Count = 0; //
// analyze what resources we are getting
//
resourceDescriptorOut = resourceListOut->Descriptors; firstIrq = TRUE; for (i=0; i<resourceListIn->Count; i++) { switch (resourceDescriptorIn[i].Type) { case CmResourceTypePort: { if ((resourceDescriptorIn + i == brokenResourceDescriptor) && (numExtraIoResDescriptor)) { for (k=0; k<numExtraIoResDescriptor; k++) { *resourceDescriptorOut = resourceDescriptorIn[i]; if (k != 0) { resourceDescriptorOut->Option = IO_RESOURCE_ALTERNATIVE; } resourceDescriptorOut->u.Port.Alignment = 1; resourceDescriptorOut->u.Port.MinimumAddress.QuadPart = brokenResourceDescriptor->u.Port.MinimumAddress.QuadPart + k * brokenResourceDescriptor->u.Port.Alignment; resourceDescriptorOut->u.Port.MaximumAddress.QuadPart = resourceDescriptorOut->u.Port.MinimumAddress.QuadPart + resourceDescriptorOut->u.Port.Length - 1; resourceDescriptorOut++; resourceListOut->Count++; } } else { *resourceDescriptorOut = resourceDescriptorIn[i]; resourceDescriptorOut++; resourceListOut->Count++; } } break; case CmResourceTypeInterrupt: { //
// keep all irqs except 9 which doesn't really work
//
if (!((resourceDescriptorIn[i].u.Interrupt.MinimumVector == 0x9) && (resourceDescriptorIn[i].u.Interrupt.MaximumVector == 0x9))) { *resourceDescriptorOut = resourceDescriptorIn[i]; if (firstIrq) { resourceDescriptorOut->Option = 0; firstIrq = FALSE; } else { resourceDescriptorOut->Option = IO_RESOURCE_ALTERNATIVE; } resourceDescriptorOut++; resourceListOut->Count++; } } break; default: *resourceDescriptorOut = resourceDescriptorIn[i]; resourceDescriptorOut++; resourceListOut->Count++; break; } } resourceListIn = (PIO_RESOURCE_LIST) (resourceDescriptorIn + resourceListIn->Count); resourceListOut = (PIO_RESOURCE_LIST) resourceDescriptorOut; }
getout: if (requirementsListOut) {
if (NT_SUCCESS(Irp->IoStatus.Status)) {
ExFreePool ((PVOID) Irp->IoStatus.Information);
} else {
Irp->IoStatus.Status = STATUS_SUCCESS; } Irp->IoStatus.Information = (ULONG_PTR) requirementsListOut; return STATUS_SUCCESS; } else { return STATUS_INVALID_PARAMETER; } } #endif // IDE_FILTER_PROMISE_TECH_RESOURCES
NTSTATUS ChannelQueryPnPDeviceState ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PFDO_EXTENSION fdoExtension; PPNP_DEVICE_STATE deviceState;
fdoExtension = (PFDO_EXTENSION) DeviceObject->DeviceExtension; DebugPrint((DBG_PNP, "QUERY_DEVICE_STATE for FDOE 0x%x\n", fdoExtension));
if(fdoExtension->PagingPathCount != 0) { deviceState = (PPNP_DEVICE_STATE) &(Irp->IoStatus.Information); SETMASK((*deviceState), PNP_DEVICE_NOT_DISABLEABLE); }
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation (Irp); return IoCallDriver (fdoExtension->AttacheeDeviceObject, Irp); }
|