NTSTATUS NTAPI PciFdoIrpQueryCapabilities(IN PIRP Irp, IN PIO_STACK_LOCATION IoStackLocation, IN PPCI_FDO_EXTENSION DeviceExtension) { PDEVICE_CAPABILITIES Capabilities; PAGED_CODE(); ASSERT_FDO(DeviceExtension); UNREFERENCED_PARAMETER(Irp); /* Get the capabilities */ Capabilities = IoStackLocation->Parameters.DeviceCapabilities.Capabilities; /* Inherit wake levels and power mappings from the higher-up capabilities */ DeviceExtension->PowerState.SystemWakeLevel = Capabilities->SystemWake; DeviceExtension->PowerState.DeviceWakeLevel = Capabilities->DeviceWake; RtlCopyMemory(DeviceExtension->PowerState.SystemStateMapping, Capabilities->DeviceState, sizeof(DeviceExtension->PowerState.SystemStateMapping)); /* Dump the capabilities and return success */ PciDebugDumpQueryCapabilities(Capabilities); return STATUS_SUCCESS; }
NTSTATUS NTAPI PciCallDownIrpStack(IN PPCI_FDO_EXTENSION DeviceExtension, IN PIRP Irp) { NTSTATUS Status; KEVENT Event; PAGED_CODE(); DPRINT1("PciCallDownIrpStack ...\n"); ASSERT_FDO(DeviceExtension); /* Initialize the wait event */ KeInitializeEvent(&Event, SynchronizationEvent, 0); /* Setup a completion routine */ IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, PciSetEventCompletion, &Event, TRUE, TRUE, TRUE); /* Call the attached device */ Status = IoCallDriver(DeviceExtension->AttachedDeviceObject, Irp); if (Status == STATUS_PENDING) { /* Wait for it to complete the request, and get its status */ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); Status = Irp->IoStatus.Status; } /* Return that status back to the caller */ return Status; }
NTSTATUS NTAPI tranirq_Constructor(IN PVOID DeviceExtension, IN PVOID Instance, IN PVOID InterfaceData, IN USHORT Version, IN USHORT Size, IN PINTERFACE Interface) { PPCI_FDO_EXTENSION FdoExtension = (PPCI_FDO_EXTENSION)DeviceExtension; ULONG BaseBus, ParentBus; INTERFACE_TYPE ParentInterface; ASSERT_FDO(FdoExtension); UNREFERENCED_PARAMETER(Instance); UNREFERENCED_PARAMETER(Version); UNREFERENCED_PARAMETER(Size); /* Make sure it's the right resource type */ if ((ULONG)InterfaceData != CmResourceTypeInterrupt) { /* Fail this invalid request */ DPRINT1("PCI - IRQ trans constructor doesn't like %p in InterfaceSpecificData\n", InterfaceData); return STATUS_INVALID_PARAMETER_3; } /* Get the bus, and use this as the interface-specific data */ BaseBus = FdoExtension->BaseBus; InterfaceData = (PVOID)BaseBus; /* Check if this is the root bus */ if (PCI_IS_ROOT_FDO(FdoExtension)) { /* It is, so there is no parent, and it's connected on the system bus */ ParentBus = 0; ParentInterface = Internal; DPRINT1(" Is root FDO\n"); } else { /* It's not, so we have to get the root bus' bus number instead */ #if 0 // when have PDO commit ParentBus = FdoExtension->PhysicalDeviceObject->DeviceExtension->ParentFdoExtension->BaseBus; ParentInterface = PCIBus; DPRINT1(" Is bridge FDO, parent bus %x, secondary bus %x\n", ParentBus, BaseBus); #endif } /* Now call the legacy HAL interface to get the correct translator */ return HalGetInterruptTranslator(ParentInterface, ParentBus, PCIBus, sizeof(TRANSLATOR_INTERFACE), 0, (PTRANSLATOR_INTERFACE)Interface, (PULONG)&InterfaceData); }
NTSTATUS NTAPI DiskUpdateRemovableGeometry ( IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension ) /*++ Routine Description: This routine updates the geometry of the disk. It will query the port driver to see if it can provide any geometry info. If not it will use the current head & sector count. Based on these values & the capacity of the drive as reported by ClassReadDriveCapacity it will determine a new cylinder count for the device. Arguments: Fdo - Supplies the functional device object whos size needs to be updated. Return Value: Returns the status of the opertion. --*/ { PCOMMON_DEVICE_EXTENSION commonExtension = &(FdoExtension->CommonExtension); PDISK_DATA diskData = commonExtension->DriverData; PDISK_GEOMETRY geometry = &(diskData->RealGeometry); NTSTATUS status; PAGED_CODE(); ASSERT_FDO(commonExtension->DeviceObject); if (FdoExtension->DeviceDescriptor) { ASSERT(FdoExtension->DeviceDescriptor->RemovableMedia); } ASSERT(TEST_FLAG(FdoExtension->DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA)); // // Attempt to determine the disk geometry. First we'll check with the // port driver to see what it suggests for a value. // status = DiskGetPortGeometry(FdoExtension, geometry); if(NT_SUCCESS(status) && ((geometry->TracksPerCylinder * geometry->SectorsPerTrack) != 0)) { FdoExtension->DiskGeometry = (*geometry); } return status; }
VOID NTAPI DiskReleasePartitioningLock( IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension ) { PDISK_DATA diskData = FdoExtension->CommonExtension.DriverData; PAGED_CODE(); ASSERT_FDO(FdoExtension->DeviceObject); KeSetEvent(&(diskData->PartitioningEvent), IO_NO_INCREMENT, FALSE); return; }
NTSTATUS NTAPI DiskReadDriveCapacity( IN PDEVICE_OBJECT Fdo ) /*++ Routine Description: This routine is used by disk.sys as a wrapper for the classpnp API ClassReadDriveCapacity. It will perform some additional operations to attempt to determine drive geometry before it calls the classpnp version of the routine. For fixed disks this involves calling DiskUpdateGeometry which will check various sources (the BIOS, the port driver) for geometry information. Arguments: Fdo - a pointer to the device object to be checked. Return Value: status of ClassReadDriveCapacity. --*/ { PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; //PDISK_DATA diskData = fdoExtension->CommonExtension.DriverData; //DISK_GEOMETRY_SOURCE diskGeometrySource = DiskGeometryUnknown; NTSTATUS status; ASSERT_FDO(Fdo); if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) { DiskUpdateRemovableGeometry(fdoExtension); } else { /* diskGeometrySource =*/ DiskUpdateGeometry(fdoExtension); } status = ClassReadDriveCapacity(Fdo); return status; }
VOID NTAPI DiskAcquirePartitioningLock( IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension ) { PDISK_DATA diskData = FdoExtension->CommonExtension.DriverData; PAGED_CODE(); ASSERT_FDO(FdoExtension->DeviceObject); KeWaitForSingleObject(&(diskData->PartitioningEvent), UserRequest, UserMode, FALSE, NULL); return; }
/* * DiskAcquirePartitioningLock * * Acquire the PartitioningEvent. * * NOTE: This function is called by several ioctl handlers which run in user context. * Because we are acquiring an exclusion object in a user thread, we have to make sure * that the thread is not killed or suspended while we are holding the event. * So we call KeEnterCriticalRegion/KeLeaveCriticalRegion while holding the PartitioningEvent. * THEREFORE, it is VERY IMPORTANT that DiskAcquirePartitioningLock and DiskReleasePartitioningLock * are called on the SAME THREAD. */ VOID DiskAcquirePartitioningLock( IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension ) { PDISK_DATA diskData = FdoExtension->CommonExtension.DriverData; PAGED_CODE(); ASSERT_FDO(FdoExtension->DeviceObject); /* * Don't let user-mode thread get suspended while we are holding the partitioning lock */ KeEnterCriticalRegion(); KeWaitForSingleObject(&(diskData->PartitioningEvent), UserRequest, KernelMode, FALSE, NULL); return; }
NTSTATUS NTAPI PciInitializeArbiters(IN PPCI_FDO_EXTENSION FdoExtension) { PPCI_INTERFACE CurrentInterface, *Interfaces; PPCI_PDO_EXTENSION PdoExtension; PPCI_ARBITER_INSTANCE ArbiterInterface; NTSTATUS Status; PCI_SIGNATURE ArbiterType; ASSERT_FDO(FdoExtension); /* Loop all the arbiters */ for (ArbiterType = PciArb_Io; ArbiterType <= PciArb_BusNumber; ArbiterType++) { /* Check if this is the extension for the Root PCI Bus */ if (!PCI_IS_ROOT_FDO(FdoExtension)) { /* Get the PDO extension */ PdoExtension = FdoExtension->PhysicalDeviceObject->DeviceExtension; ASSERT_PDO(PdoExtension); /* Skip this bus if it does subtractive decode */ if (PdoExtension->Dependent.type1.SubtractiveDecode) { DPRINT1("PCI Not creating arbiters for subtractive bus %u\n", PdoExtension->Dependent.type1.SubtractiveDecode); continue; } } /* Query all the registered arbiter interfaces */ Interfaces = PciInterfaces; while (*Interfaces) { /* Find the one that matches the arbiter currently being setup */ CurrentInterface = *Interfaces; if (CurrentInterface->Signature == ArbiterType) break; Interfaces++; } /* Check if the required arbiter was not found in the list */ if (!*Interfaces) { /* Skip this arbiter and try the next one */ DPRINT1("PCI - FDO ext 0x%p no %s arbiter.\n", FdoExtension, PciArbiterNames[ArbiterType - PciArb_Io]); continue; } /* An arbiter was found, allocate an instance for it */ Status = STATUS_INSUFFICIENT_RESOURCES; ArbiterInterface = ExAllocatePoolWithTag(PagedPool, sizeof(PCI_ARBITER_INSTANCE), PCI_POOL_TAG); if (!ArbiterInterface) break; /* Setup the instance */ ArbiterInterface->BusFdoExtension = FdoExtension; ArbiterInterface->Interface = CurrentInterface; swprintf(ArbiterInterface->InstanceName, L"PCI %S (b=%02x)", PciArbiterNames[ArbiterType - PciArb_Io], FdoExtension->BaseBus); /* Call the interface initializer for it */ Status = CurrentInterface->Initializer(ArbiterInterface); if (!NT_SUCCESS(Status)) break; /* Link it with this FDO */ PcipLinkSecondaryExtension(&FdoExtension->SecondaryExtension, &FdoExtension->SecondaryExtLock, &ArbiterInterface->Header, ArbiterType, PciArbiterDestructor); /* This arbiter is now initialized, move to the next one */ DPRINT1("PCI - FDO ext 0x%p %S arbiter initialized (context 0x%p).\n", FdoExtension, L"ARBITER HEADER MISSING", //ArbiterInterface->CommonInstance.Name, ArbiterInterface); Status = STATUS_SUCCESS; } /* Return to caller */ return Status; }
NTSTATUS SpPagingPathNotificationCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP LowerIrp, IN PDEVICE_OBJECT Fdo ) { PIRP upperIrp = LowerIrp->AssociatedIrp.MasterIrp; PIO_STACK_LOCATION lowerStack = IoGetCurrentIrpStackLocation(LowerIrp); PIO_STACK_LOCATION upperStack = IoGetCurrentIrpStackLocation(upperIrp); PDEVICE_OBJECT pdo = upperStack->DeviceObject; PADAPTER_EXTENSION lowerExtension; PLOGICAL_UNIT_EXTENSION upperExtension; ASSERT(Fdo != NULL); ASSERT(pdo != NULL); DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: Completion of " "paging notification irp %#p sent due to irp %#p\n", LowerIrp, upperIrp)); lowerExtension = (PADAPTER_EXTENSION) Fdo->DeviceExtension; upperExtension = (PLOGICAL_UNIT_EXTENSION) pdo->DeviceExtension; ASSERT_FDO(lowerExtension->DeviceObject); ASSERT_PDO(upperExtension->DeviceObject); DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: irp status %#08lx\n", LowerIrp->IoStatus.Status)); if(NT_SUCCESS(LowerIrp->IoStatus.Status)) { PUCHAR typeName = "INSERT TYPE HERE"; PULONG lowerCount; PULONG upperCount; // // The parameters have already been erased from the lower irp stack // location - use the parameters from the upper once since they're // just a copy. // switch(upperStack->Parameters.UsageNotification.Type) { case DeviceUsageTypePaging: { lowerCount = &(lowerExtension->CommonExtension.PagingPathCount); upperCount = &(upperExtension->CommonExtension.PagingPathCount); typeName = "PagingPathCount"; break; } case DeviceUsageTypeHibernation: { lowerCount = &(lowerExtension->CommonExtension.HibernatePathCount); upperCount = &(upperExtension->CommonExtension.HibernatePathCount); typeName = "HibernatePathCount"; break; } case DeviceUsageTypeDumpFile: { lowerCount = &(lowerExtension->CommonExtension.DumpPathCount); upperCount = &(upperExtension->CommonExtension.DumpPathCount); typeName = "DumpPathCount"; break; } default: { typeName = "unknown type"; lowerCount = upperCount = NULL; break; } } if(lowerCount != NULL) { IoAdjustPagingPathCount( lowerCount, upperStack->Parameters.UsageNotification.InPath ); DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: " "Fdo %s count - %d\n", typeName, *lowerCount)); IoInvalidateDeviceState(lowerExtension->LowerPdo); } if(upperCount != NULL) { IoAdjustPagingPathCount( upperCount, upperStack->Parameters.UsageNotification.InPath ); DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: " "Pdo %s count - %d\n", typeName, *upperCount)); IoInvalidateDeviceState(upperExtension->DeviceObject); } } upperIrp->IoStatus = LowerIrp->IoStatus; SpReleaseRemoveLock(lowerExtension->CommonExtension.DeviceObject, LowerIrp); SpReleaseRemoveLock(upperExtension->CommonExtension.DeviceObject, upperIrp); IoMarkIrpPending(upperIrp); SpCompleteRequest(upperExtension->CommonExtension.DeviceObject, upperIrp, NULL, IO_NO_INCREMENT); IoFreeIrp(LowerIrp); return STATUS_MORE_PROCESSING_REQUIRED; }
VOID NTAPI DiskDeleteSymbolicLinks( IN PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This routine will delete the well known name (symlink) for the specified device. It generates the link name using information stored in the device extension Arguments: DeviceObject - the device object we are unlinking Return Value: status --*/ { PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; PDISK_DATA diskData = commonExtension->DriverData; WCHAR wideLinkName[64]; UNICODE_STRING unicodeLinkName; PAGED_CODE(); if(diskData->LinkStatus.WellKnownNameCreated) { swprintf(wideLinkName, L"\\Device\\Harddisk%d\\Partition%d", commonExtension->PartitionZeroExtension->DeviceNumber, (commonExtension->IsFdo ? 0 : commonExtension->PartitionNumber)); RtlInitUnicodeString(&unicodeLinkName, wideLinkName); IoDeleteSymbolicLink(&unicodeLinkName); diskData->LinkStatus.WellKnownNameCreated = FALSE; } if(diskData->LinkStatus.PhysicalDriveLinkCreated) { ASSERT_FDO(DeviceObject); swprintf(wideLinkName, L"\\DosDevices\\PhysicalDrive%d", commonExtension->PartitionZeroExtension->DeviceNumber); RtlInitUnicodeString(&unicodeLinkName, wideLinkName); IoDeleteSymbolicLink(&unicodeLinkName); diskData->LinkStatus.PhysicalDriveLinkCreated = FALSE; } return; }
VOID ScsiPortRemoveAdapter( IN PDEVICE_OBJECT AdapterObject, IN BOOLEAN Surprise ) { PADAPTER_EXTENSION adapter = AdapterObject->DeviceExtension; PCOMMON_EXTENSION commonExtension = AdapterObject->DeviceExtension; NTSTATUS status = STATUS_SUCCESS; PAGED_CODE(); ASSERT_FDO(AdapterObject); ASSERT(adapter->IsPnp); // // Set the flag PD_ADAPTER_REMOVED to keep scsiport from calling into the // miniport after we've started this teardown. // if(Surprise == FALSE) { PVOID sectionHandle; KIRQL oldIrql; // // Wait until all outstanding requests have been completed. // SpWaitForRemoveLock(AdapterObject, AdapterObject); // // If the device is started we should uninitialize the miniport and // release it's resources. Fortunately this is exactly what stop does. // if((commonExtension->CurrentPnpState != IRP_MN_SURPRISE_REMOVAL) && ((commonExtension->CurrentPnpState == IRP_MN_START_DEVICE) || (commonExtension->PreviousPnpState == IRP_MN_START_DEVICE))) { // // Okay. If this adapter can't support remove then we're dead // ASSERT(SpIsAdapterControlTypeSupported(adapter, ScsiStopAdapter) == TRUE); // // Stop the miniport now that it's safe. // SpEnableDisableAdapter(adapter, FALSE); // // Mark the adapter as removed. // #ifdef ALLOC_PRAGMA sectionHandle = MmLockPagableCodeSection(ScsiPortRemoveAdapter); InterlockedIncrement(&SpPAGELOCKLockCount); #endif KeAcquireSpinLock(&(adapter->SpinLock), &oldIrql); adapter->SynchronizeExecution(adapter->InterruptObject, SpRemoveAdapterSynchronized, adapter); KeReleaseSpinLock(&(adapter->SpinLock), oldIrql); #ifdef ALLOC_PRAGMA InterlockedDecrement(&SpPAGELOCKLockCount); MmUnlockPagableImageSection(sectionHandle); #endif } SpReapChildren(adapter); } if(commonExtension->WmiInitialized == TRUE) { // // Destroy all our WMI resources and unregister with WMI. // IoWMIRegistrationControl(AdapterObject, WMIREG_ACTION_DEREGISTER); SpWmiRemoveFreeMiniPortRequestItems(adapter); commonExtension->WmiInitialized = FALSE; } // // If we were surprise removed then this has already been done once. // In that case don't try to run the cleanup code a second time even though // it's safe to do so. // SpDeleteDeviceMapEntry(AdapterObject); SpDestroyAdapter(adapter, Surprise); return; }
NTSTATUS SpWmiInitializeFreeRequestList( IN PDEVICE_OBJECT DeviceObject, IN ULONG NumberOfItems ) /*++ Routine Description: Call that initializes the WmiFreeMiniPortRequestList, this call MUST be completed prior to any manipulatio of the WmiFreeMiniPortRequestList The list will be initialized with at most the number of cells requested. If the list has already been initialized, we raise the watermark by the number of Items requested. Arguments: DeviceObject - Device Object that this list belongs to NumberOfItems - requested number of free cells Return Value: Return the SUCESS if list was initialized succesfully STATUS_INSUFFICIENT_REOSOURCES - Indicates that we could not allocate enough memory for the list header Notes: --*/ { PADAPTER_EXTENSION fdoExtension; ULONG itemsInserted; KIRQL oldIrql; PAGED_CODE(); // Routine is paged until locked down. // // Obtain a pointer to the functional device extension (for the adapter). // if ( ((PCOMMON_EXTENSION)DeviceObject->DeviceExtension)->IsPdo ) { fdoExtension = ((PLOGICAL_UNIT_EXTENSION)DeviceObject->DeviceExtension) ->AdapterExtension; } else { fdoExtension = DeviceObject->DeviceExtension; } // If the list has been initalized increase the watermark if (fdoExtension->WmiFreeMiniPortRequestInitialized) { DebugPrint((2, "SpWmiInitializeFreeRequestList:" " Increased watermark for : %p\n", fdoExtension)); InterlockedExchangeAdd (&(fdoExtension->WmiFreeMiniPortRequestWatermark), NumberOfItems); while (fdoExtension->WmiFreeMiniPortRequestCount < fdoExtension->WmiFreeMiniPortRequestWatermark) { // Add free cells until the count reaches the watermark SpWmiPushFreeRequestItem(fdoExtension); } return (STATUS_SUCCESS); } // Only PDO's should be calling when the list has not been initialized ASSERT_FDO(DeviceObject); // Assignt he list we just initialized to the pointer in the // fdoExtension (and save the lock pointer also) KeInitializeSpinLock(&(fdoExtension->WmiFreeMiniPortRequestLock)); ExInitializeSListHead(&(fdoExtension->WmiFreeMiniPortRequestList)); DebugPrint((1, "SpWmiInitializeFreeRequestList:" " Initialized WmiFreeRequestList for: %p\n", fdoExtension)); // Set the initialized flag fdoExtension->WmiFreeMiniPortRequestInitialized = TRUE; // Set the watermark, and the count to 0 fdoExtension->WmiFreeMiniPortRequestWatermark = 0; fdoExtension->WmiFreeMiniPortRequestCount = 0; // Attempt to add free cells to the free list for (itemsInserted = 0; itemsInserted < NumberOfItems; itemsInserted++) { // Make a request to push a NULL item, so that the // allocation will be done by the next function // // At this point we don't care about the return value // because after we set the watermark, scsiport's free-cell // repopulation code will try to get the free list cell count // back to the watermark. (So if we fail to add all the requested // free cells, the repopulation code will attempt again for us // at a later time) SpWmiPushFreeRequestItem(fdoExtension); } // Now set the watermark to the correct value fdoExtension->WmiFreeMiniPortRequestWatermark = NumberOfItems; return(STATUS_SUCCESS); }