X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fntoskrnl%2Fio%2Fpnpmgr.c;h=89946f70070517c662af29ae40ddcf1040e1676b;hp=1a6f3ab9801985b4e5b15e903e4bfbb1bb4ee05f;hb=10e6548a78c91c83dc4d7e45c44920c0644f1c50;hpb=026d788dcc97daf862b8847bb6afdfe1d0123732 diff --git a/reactos/ntoskrnl/io/pnpmgr.c b/reactos/ntoskrnl/io/pnpmgr.c index 1a6f3ab9801..89946f70070 100644 --- a/reactos/ntoskrnl/io/pnpmgr.c +++ b/reactos/ntoskrnl/io/pnpmgr.c @@ -1,17 +1,16 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/pnpmgr.c * PURPOSE: Initializes the PnP manager * * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * Hervé Poussineau (hpoussin@reactos.org) */ /* INCLUDES ******************************************************************/ #include -#include #define NDEBUG #include @@ -24,6 +23,80 @@ KSPIN_LOCK IopDeviceTreeLock; /* DATA **********************************************************************/ PDRIVER_OBJECT IopRootDriverObject; +PIO_BUS_TYPE_GUID_LIST IopBusTypeGuidList = NULL; + +// Static CRC table +ULONG crc32Table[256] = +{ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, +}; + /* FUNCTIONS *****************************************************************/ @@ -31,7 +104,33 @@ PDEVICE_NODE FASTCALL IopGetDeviceNode( PDEVICE_OBJECT DeviceObject) { - return DeviceObject->DeviceObjectExtension->DeviceNode; + return ((PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension)->DeviceNode; +} + +NTSTATUS +STDCALL +IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode, + PDEVICE_CAPABILITIES DeviceCaps) +{ + IO_STATUS_BLOCK StatusBlock; + IO_STACK_LOCATION Stack; + + /* Set up the Header */ + RtlZeroMemory(DeviceCaps, sizeof(DEVICE_CAPABILITIES)); + DeviceCaps->Size = sizeof(DEVICE_CAPABILITIES); + DeviceCaps->Version = 1; + DeviceCaps->Address = -1; + DeviceCaps->UINumber = -1; + + /* Set up the Stack */ + RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION)); + Stack.Parameters.DeviceCapabilities.Capabilities = DeviceCaps; + + /* Send the IRP */ + return IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject, + &StatusBlock, + IRP_MN_QUERY_CAPABILITIES, + &Stack); } /* @@ -59,11 +158,13 @@ IoGetDeviceProperty( OUT PULONG ResultLength) { PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject); + DEVICE_CAPABILITIES DeviceCaps; ULONG Length; PVOID Data = NULL; PWSTR Ptr; + NTSTATUS Status; - DPRINT("IoGetDeviceProperty(%x %d)\n", DeviceObject, DeviceProperty); + DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject, DeviceProperty); if (DeviceNode == NULL) return STATUS_INVALID_DEVICE_REQUEST; @@ -77,23 +178,30 @@ IoGetDeviceProperty( /* Complete, untested */ case DevicePropertyBusTypeGuid: - *ResultLength = 39 * sizeof(WCHAR); - if (BufferLength < (39 * sizeof(WCHAR))) - return STATUS_BUFFER_TOO_SMALL; - swprintf((PWSTR)PropertyBuffer, - L"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - DeviceNode->BusTypeGuid.Data1, - DeviceNode->BusTypeGuid.Data2, - DeviceNode->BusTypeGuid.Data3, - DeviceNode->BusTypeGuid.Data4[0], - DeviceNode->BusTypeGuid.Data4[1], - DeviceNode->BusTypeGuid.Data4[2], - DeviceNode->BusTypeGuid.Data4[3], - DeviceNode->BusTypeGuid.Data4[4], - DeviceNode->BusTypeGuid.Data4[5], - DeviceNode->BusTypeGuid.Data4[6], - DeviceNode->BusTypeGuid.Data4[7]); - return STATUS_SUCCESS; + /* Sanity check */ + if ((DeviceNode->ChildBusTypeIndex != 0xFFFF) && + (DeviceNode->ChildBusTypeIndex < IopBusTypeGuidList->GuidCount)) + { + /* Return the GUID */ + *ResultLength = sizeof(GUID); + + /* Check if the buffer given was large enough */ + if (BufferLength < *ResultLength) + { + return STATUS_BUFFER_TOO_SMALL; + } + + /* Copy the GUID */ + RtlCopyMemory(PropertyBuffer, + &(IopBusTypeGuidList->Guids[DeviceNode->ChildBusTypeIndex]), + sizeof(GUID)); + return STATUS_SUCCESS; + } + else + { + return STATUS_OBJECT_NAME_NOT_FOUND; + } + break; case DevicePropertyLegacyBusType: Length = sizeof(INTERFACE_TYPE); @@ -101,9 +209,29 @@ IoGetDeviceProperty( break; case DevicePropertyAddress: - Length = sizeof(ULONG); - Data = &DeviceNode->Address; - break; + + /* Query the device caps */ + Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCaps); + if (NT_SUCCESS(Status) && (DeviceCaps.Address != -1)) + { + /* Return length */ + *ResultLength = sizeof(ULONG); + + /* Check if the buffer given was large enough */ + if (BufferLength < *ResultLength) + { + return STATUS_BUFFER_TOO_SMALL; + } + + /* Return address */ + *(PULONG)PropertyBuffer = DeviceCaps.Address; + return STATUS_SUCCESS; + } + else + { + return STATUS_OBJECT_NAME_NOT_FOUND; + } + break; // case DevicePropertyUINumber: // if (DeviceNode->CapabilityFlags == NULL) @@ -160,7 +288,7 @@ IoGetDeviceProperty( KeyNameBuffer = ExAllocatePool(PagedPool, (49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length); - DPRINT("KeyNameBuffer: %x, value %S\n", + DPRINT("KeyNameBuffer: 0x%p, value %S\n", KeyNameBuffer, RegistryPropertyName); if (KeyNameBuffer == NULL) @@ -438,38 +566,6 @@ IoRequestDeviceEject( } -BOOLEAN -IopCreateUnicodeString( - PUNICODE_STRING Destination, - PWSTR Source, - POOL_TYPE PoolType) -{ - ULONG Length; - - if (!Source) - { - RtlInitUnicodeString(Destination, NULL); - return TRUE; - } - - Length = (wcslen(Source) + 1) * sizeof(WCHAR); - - Destination->Buffer = ExAllocatePool(PoolType, Length); - - if (Destination->Buffer == NULL) - { - return FALSE; - } - - RtlCopyMemory(Destination->Buffer, Source, Length); - - Destination->MaximumLength = Length; - - Destination->Length = Length - sizeof(WCHAR); - - return TRUE; -} - NTSTATUS IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject) { @@ -487,6 +583,66 @@ IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject) return STATUS_UNSUCCESSFUL; } +USHORT +STDCALL +IopGetBusTypeGuidIndex(LPGUID BusTypeGuid) +{ + USHORT i = 0, FoundIndex = 0xFFFF; + ULONG NewSize; + PVOID NewList; + + /* Acquire the lock */ + ExAcquireFastMutex(&IopBusTypeGuidList->Lock); + + /* Loop all entries */ + while (i < IopBusTypeGuidList->GuidCount) + { + /* Try to find a match */ + if (RtlCompareMemory(BusTypeGuid, + &IopBusTypeGuidList->Guids[i], + sizeof(GUID))) + { + /* Found it */ + FoundIndex = i; + goto Quickie; + } + } + + /* Check if we have to grow the list */ + if (IopBusTypeGuidList->GuidCount) + { + /* Calculate the new size */ + NewSize = sizeof(IO_BUS_TYPE_GUID_LIST) + + (sizeof(GUID) * IopBusTypeGuidList->GuidCount); + + /* Allocate the new copy */ + NewList = ExAllocatePool(PagedPool, NewSize); + + /* Now copy them, decrease the size too */ + NewSize -= sizeof(GUID); + RtlCopyMemory(NewList, IopBusTypeGuidList, NewSize); + + /* Free the old list */ + ExFreePool(IopBusTypeGuidList); + + /* Use the new buffer */ + IopBusTypeGuidList = NewList; + } + + /* Copy the new GUID */ + RtlCopyMemory(&IopBusTypeGuidList->Guids[IopBusTypeGuidList->GuidCount], + BusTypeGuid, + sizeof(GUID)); + + /* The new entry is the index */ + FoundIndex = IopBusTypeGuidList->GuidCount; + IopBusTypeGuidList->GuidCount++; + +Quickie: + ExReleaseFastMutex(&IopBusTypeGuidList->Lock); + return FoundIndex; +} + /* * DESCRIPTION * Creates a device node @@ -510,7 +666,7 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode, NTSTATUS Status; KIRQL OldIrql; - DPRINT("ParentNode %x PhysicalDeviceObject %x\n", + DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p\n", ParentNode, PhysicalDeviceObject); Node = (PDEVICE_NODE)ExAllocatePool(NonPagedPool, sizeof(DEVICE_NODE)); @@ -537,7 +693,7 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode, Node->PhysicalDeviceObject = PhysicalDeviceObject; - PhysicalDeviceObject->DeviceObjectExtension->DeviceNode = Node; + ((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode = Node; if (ParentNode) { @@ -550,6 +706,7 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode, } ParentNode->Child = Node; KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql); + Node->Level = ParentNode->Level + 1; } *DeviceNode = Node; @@ -728,9 +885,9 @@ IopTraverseDeviceTree( { NTSTATUS Status; - DPRINT("Context %x\n", Context); + DPRINT("Context 0x%p\n", Context); - DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n", + DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n", Context->DeviceNode, Context->FirstDeviceNode, Context->Action, Context->Context); /* Start from the specified device node */ @@ -886,13 +1043,48 @@ IopSetDeviceInstanceData(HANDLE InstanceKey, &KeyName, 0, REG_RESOURCE_REQUIREMENTS_LIST, - &DeviceNode->ResourceRequirements, + DeviceNode->ResourceRequirements, DeviceNode->ResourceRequirements->ListSize); } ZwClose(LogConfKey); } +#if 0 + if (DeviceNode->PhysicalDeviceObject != NULL) + { + /* Create the 'Control' key */ + RtlInitUnicodeString(&KeyName, + L"Control"); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE | OBJ_OPENIF, + InstanceKey, + NULL); + Status = ZwCreateKey(&LogConfKey, + KEY_ALL_ACCESS, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + NULL); + if (NT_SUCCESS(Status)) + { + ULONG Reference = (ULONG)DeviceNode->PhysicalDeviceObject; + RtlInitUnicodeString(&KeyName, + L"DeviceReference"); + Status = ZwSetValueKey(LogConfKey, + &KeyName, + 0, + REG_DWORD, + &Reference, + sizeof(PVOID)); + + ZwClose(LogConfKey); + } + } +#endif + DPRINT("IopSetDeviceInstanceData() done\n"); return STATUS_SUCCESS; @@ -908,58 +1100,65 @@ IopAssignDeviceResources( PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw, DescriptorTranslated; ULONG NumberOfResources = 0; ULONG i; - + NTSTATUS Status; + /* Fill DeviceNode->ResourceList and DeviceNode->ResourceListTranslated; * by using DeviceNode->ResourceRequirements */ - + if (!DeviceNode->ResourceRequirements || DeviceNode->ResourceRequirements->AlternativeLists == 0) { DeviceNode->ResourceList = DeviceNode->ResourceListTranslated = NULL; return STATUS_SUCCESS; } - + /* FIXME: that's here that PnP arbiter should go */ /* Actually, simply use resource list #0 as assigned resource list */ ResourceList = &DeviceNode->ResourceRequirements->List[0]; if (ResourceList->Version != 1 || ResourceList->Revision != 1) - return STATUS_REVISION_MISMATCH; - - DeviceNode->ResourceList = ExAllocatePool(PagedPool, + { + Status = STATUS_REVISION_MISMATCH; + goto ByeBye; + } + + DeviceNode->ResourceList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST) + ResourceList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); if (!DeviceNode->ResourceList) - return STATUS_INSUFFICIENT_RESOURCES; - - DeviceNode->ResourceListTranslated = ExAllocatePool(PagedPool, + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto ByeBye; + } + + DeviceNode->ResourceListTranslated = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST) + ResourceList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); if (!DeviceNode->ResourceListTranslated) { - ExFreePool(DeviceNode->ResourceList); - return STATUS_INSUFFICIENT_RESOURCES; + Status = STATUS_INSUFFICIENT_RESOURCES; + goto ByeBye; } - + DeviceNode->ResourceList->Count = 1; DeviceNode->ResourceList->List[0].InterfaceType = DeviceNode->ResourceRequirements->InterfaceType; DeviceNode->ResourceList->List[0].BusNumber = DeviceNode->ResourceRequirements->BusNumber; DeviceNode->ResourceList->List[0].PartialResourceList.Version = 1; DeviceNode->ResourceList->List[0].PartialResourceList.Revision = 1; - + DeviceNode->ResourceListTranslated->Count = 1; DeviceNode->ResourceListTranslated->List[0].InterfaceType = DeviceNode->ResourceRequirements->InterfaceType; DeviceNode->ResourceListTranslated->List[0].BusNumber = DeviceNode->ResourceRequirements->BusNumber; DeviceNode->ResourceListTranslated->List[0].PartialResourceList.Version = 1; DeviceNode->ResourceListTranslated->List[0].PartialResourceList.Revision = 1; - + for (i = 0; i < ResourceList->Count; i++) { ResourceDescriptor = &ResourceList->Descriptors[i]; - + if (ResourceDescriptor->Option == 0 || ResourceDescriptor->Option == IO_RESOURCE_PREFERRED) { DescriptorRaw = &DeviceNode->ResourceList->List[0].PartialResourceList.PartialDescriptors[NumberOfResources]; DescriptorTranslated = &DeviceNode->ResourceListTranslated->List[0].PartialResourceList.PartialDescriptors[NumberOfResources]; NumberOfResources++; - + /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */ DescriptorRaw->Type = DescriptorTranslated->Type = ResourceDescriptor->Type; DescriptorRaw->ShareDisposition = DescriptorTranslated->ShareDisposition = ResourceDescriptor->ShareDisposition; @@ -968,23 +1167,81 @@ IopAssignDeviceResources( { case CmResourceTypePort: { + ULONG AddressSpace = 0; /* IO space */ DescriptorRaw->u.Port.Start = ResourceDescriptor->u.Port.MinimumAddress; DescriptorRaw->u.Port.Length = DescriptorTranslated->u.Port.Length = ResourceDescriptor->u.Port.Length; - /*FIXME: DescriptorTranslated->u.Port.Start? */ + if (!HalTranslateBusAddress( + DeviceNode->ResourceRequirements->InterfaceType, + DeviceNode->ResourceRequirements->BusNumber, + DescriptorRaw->u.Port.Start, + &AddressSpace, + &DescriptorTranslated->u.Port.Start)) + { + Status = STATUS_UNSUCCESSFUL; + goto ByeBye; + } break; } case CmResourceTypeInterrupt: { - DescriptorRaw->u.Interrupt.Vector = 0; - /* FIXME: if IRQ 9 is in the possible range, use it. - * This should be a PCI device */ - if (ResourceDescriptor->u.Interrupt.MinimumVector <= 9 - && ResourceDescriptor->u.Interrupt.MaximumVector >= 9) - DescriptorRaw->u.Interrupt.Level = 9; - else - DescriptorRaw->u.Interrupt.Level = ResourceDescriptor->u.Interrupt.MinimumVector; - + INTERFACE_TYPE BusType; + ULONG SlotNumber; + ULONG ret; + UCHAR Irq; + + DescriptorRaw->u.Interrupt.Level = 0; + DescriptorRaw->u.Interrupt.Vector = ResourceDescriptor->u.Interrupt.MinimumVector; + /* FIXME: HACK: if we have a PCI device, we try + * to keep the IRQ assigned by the BIOS */ + if (NT_SUCCESS(IoGetDeviceProperty( + DeviceNode->PhysicalDeviceObject, + DevicePropertyLegacyBusType, + sizeof(INTERFACE_TYPE), + &BusType, + &ret)) && BusType == PCIBus) + { + /* We have a PCI bus */ + if (NT_SUCCESS(IoGetDeviceProperty( + DeviceNode->PhysicalDeviceObject, + DevicePropertyAddress, + sizeof(ULONG), + &SlotNumber, + &ret)) && SlotNumber > 0) + { + /* We have a good slot number */ + ret = HalGetBusDataByOffset(PCIConfiguration, + DeviceNode->ResourceRequirements->BusNumber, + SlotNumber, + &Irq, + 0x3c /* PCI_INTERRUPT_LINE */, + sizeof(UCHAR)); + if (ret != 0 && ret != 2 + && ResourceDescriptor->u.Interrupt.MinimumVector <= Irq + && ResourceDescriptor->u.Interrupt.MaximumVector >= Irq) + { + /* The device already has an assigned IRQ */ + DescriptorRaw->u.Interrupt.Vector = Irq; + } + else + { + DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n", + DescriptorRaw->u.Interrupt.Vector, + &DeviceNode->InstancePath); + Irq = (UCHAR)DescriptorRaw->u.Interrupt.Vector; + ret = HalSetBusDataByOffset(PCIConfiguration, + DeviceNode->ResourceRequirements->BusNumber, + SlotNumber, + &Irq, + 0x3c /* PCI_INTERRUPT_LINE */, + sizeof(UCHAR)); + if (ret == 0 || ret == 2) + KEBUGCHECK(0); + } + } + } + + DescriptorTranslated->u.Interrupt.Level = 0; DescriptorTranslated->u.Interrupt.Vector = HalGetInterruptVector( DeviceNode->ResourceRequirements->InterfaceType, DeviceNode->ResourceRequirements->BusNumber, @@ -997,15 +1254,24 @@ IopAssignDeviceResources( } case CmResourceTypeMemory: { + ULONG AddressSpace = 1; /* Memory space */ DescriptorRaw->u.Memory.Start = ResourceDescriptor->u.Memory.MinimumAddress; DescriptorRaw->u.Memory.Length = DescriptorTranslated->u.Memory.Length - = ResourceDescriptor->u.Port.Length; - /*FIXME: DescriptorTranslated->u.Memory.Start? */ + = ResourceDescriptor->u.Memory.Length; + if (!HalTranslateBusAddress( + DeviceNode->ResourceRequirements->InterfaceType, + DeviceNode->ResourceRequirements->BusNumber, + DescriptorRaw->u.Memory.Start, + &AddressSpace, + &DescriptorTranslated->u.Memory.Start)) + { + Status = STATUS_UNSUCCESSFUL; + goto ByeBye; + } break; } case CmResourceTypeDma: { - DPRINT1("IopAssignDeviceResources(): CmResourceTypeDma case not implemented\n"); DescriptorRaw->u.Dma.Channel = DescriptorTranslated->u.Dma.Channel = ResourceDescriptor->u.Dma.MinimumChannel; DescriptorRaw->u.Dma.Port = DescriptorTranslated->u.Dma.Port @@ -1043,13 +1309,136 @@ IopAssignDeviceResources( NumberOfResources--; } } - + } - + DeviceNode->ResourceList->List[0].PartialResourceList.Count = NumberOfResources; DeviceNode->ResourceListTranslated->List[0].PartialResourceList.Count = NumberOfResources; - + return STATUS_SUCCESS; + +ByeBye: + if (DeviceNode->ResourceList) + { + ExFreePool(DeviceNode->ResourceList); + DeviceNode->ResourceList = NULL; + } + if (DeviceNode->ResourceListTranslated) + { + ExFreePool(DeviceNode->ResourceListTranslated); + DeviceNode->ResourceListTranslated = NULL; + } + + return Status; +} + + +/* + * IopGetParentIdPrefix + * + * Retrieve (or create) a string which identifies a device. + * + * Parameters + * DeviceNode + * Pointer to device node. + * ParentIdPrefix + * Pointer to the string where is returned the parent node identifier + * + * Remarks + * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is + * valid and its Buffer field is NULL-terminated. The caller needs to + * to free the string with RtlFreeUnicodeString when it is no longer + * needed. + */ + +NTSTATUS +IopGetParentIdPrefix( + PDEVICE_NODE DeviceNode, + PUNICODE_STRING ParentIdPrefix) +{ + ULONG KeyNameBufferLength; + PWSTR KeyNameBuffer = NULL; + PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation = NULL; + UNICODE_STRING KeyName; + UNICODE_STRING KeyValue; + UNICODE_STRING ValueName; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hKey = INVALID_HANDLE_VALUE; + PBYTE currentByte; + ULONG crc32 = 0; + ULONG i; + NTSTATUS Status; + + /* HACK: As long as some devices have a NULL device + * instance path, the following test is required :( + */ + if (DeviceNode->Parent->InstancePath.Length == 0) + return STATUS_UNSUCCESSFUL; + + /* 1. Try to retrieve ParentIdPrefix from registry */ + KeyNameBufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MAX_PATH * sizeof(WCHAR); + ParentIdPrefixInformation = ExAllocatePool(PagedPool, KeyNameBufferLength + sizeof(WCHAR)); + if (!ParentIdPrefixInformation) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + KeyNameBuffer = ExAllocatePool(PagedPool, (49 * sizeof(WCHAR)) + DeviceNode->Parent->InstancePath.Length); + if (!KeyNameBuffer) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + wcscpy(KeyNameBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); + wcscat(KeyNameBuffer, DeviceNode->Parent->InstancePath.Buffer); + RtlInitUnicodeString(&KeyName, KeyNameBuffer); + InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); + Status = ZwOpenKey(&hKey, KEY_QUERY_VALUE | KEY_SET_VALUE, &ObjectAttributes); + if (!NT_SUCCESS(Status)) + goto cleanup; + RtlInitUnicodeString(&ValueName, L"ParentIdPrefix"); + Status = ZwQueryValueKey( + hKey, &ValueName, + KeyValuePartialInformation, ParentIdPrefixInformation, + KeyNameBufferLength, &KeyNameBufferLength); + if (NT_SUCCESS(Status)) + { + if (ParentIdPrefixInformation->Type != REG_SZ) + Status = STATUS_UNSUCCESSFUL; + goto cleanup; + } + if (Status != STATUS_OBJECT_NAME_NOT_FOUND) + goto cleanup; + + /* 2. Create the ParentIdPrefix value */ + currentByte = (PBYTE)DeviceNode->Parent; + for (i = 0; i < sizeof(DEVICE_NODE); i++, currentByte++) + crc32 = (crc32 >> 8) ^ crc32Table[*currentByte ^ (crc32 & 0xff)]; + crc32 = ~crc32; + KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data; + swprintf(KeyValue.Buffer, L"%lx&%lx", DeviceNode->Parent->Level, crc32); + + /* 3. Try to write the ParentIdPrefix to registry */ + RtlInitUnicodeString(&KeyValue, KeyValue.Buffer); + Status = ZwSetValueKey( + hKey, &ValueName, + 0, REG_SZ, + (PVOID)KeyValue.Buffer, + (wcslen(KeyValue.Buffer) + 1) * sizeof(WCHAR)); + +cleanup: + if (NT_SUCCESS(Status)) + { + /* Duplicate the string to return it */ + KeyValue.Length = KeyValue.MaximumLength = ParentIdPrefixInformation->DataLength; + KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data; + Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &KeyValue, ParentIdPrefix); + } + ExFreePool(ParentIdPrefixInformation); + ExFreePool(KeyNameBuffer); + if (hKey != INVALID_HANDLE_VALUE) + ZwClose(hKey); + return Status; } @@ -1088,10 +1477,11 @@ IopActionInterrogateDeviceStack( USHORT TotalLength; HANDLE InstanceKey = NULL; UNICODE_STRING ValueName; + UNICODE_STRING ParentIdPrefix = { 0 }; DEVICE_CAPABILITIES DeviceCapabilities; DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode, Context); - DPRINT("PDO %x\n", DeviceNode->PhysicalDeviceObject); + DPRINT("PDO 0x%p\n", DeviceNode->PhysicalDeviceObject); ParentDeviceNode = (PDEVICE_NODE)Context; @@ -1146,6 +1536,27 @@ IopActionInterrogateDeviceStack( DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); } + DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n"); + + Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCapabilities); + if (!NT_SUCCESS(Status)) + { + DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status); + } + + DeviceNode->CapabilityFlags = *(PULONG)((ULONG_PTR)&DeviceCapabilities + 4); + + if (!DeviceCapabilities.UniqueID) + { + /* Device has not a unique ID. We need to prepend parent bus unique identifier */ + DPRINT("Instance ID is not unique\n"); + Status = IopGetParentIdPrefix(DeviceNode, &ParentIdPrefix); + if (!NT_SUCCESS(Status)) + { + DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status); + } + } + DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n"); Stack.Parameters.QueryId.IdType = BusQueryInstanceID; @@ -1158,6 +1569,13 @@ IopActionInterrogateDeviceStack( { /* Append the instance id string */ wcscat(InstancePath, L"\\"); + if (ParentIdPrefix.Length > 0) + { + /* Add information from parent bus device to InstancePath */ + wcscat(InstancePath, ParentIdPrefix.Buffer); + if (*(PWSTR)IoStatusBlock.Information) + wcscat(InstancePath, L"&"); + } wcscat(InstancePath, (PWSTR)IoStatusBlock.Information); /* @@ -1169,37 +1587,9 @@ IopActionInterrogateDeviceStack( { DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); } + RtlFreeUnicodeString(&ParentIdPrefix); - RtlZeroMemory(&DeviceCapabilities, sizeof(DEVICE_CAPABILITIES)); - DeviceCapabilities.Size = sizeof(DEVICE_CAPABILITIES); - DeviceCapabilities.Version = 1; - DeviceCapabilities.Address = -1; - DeviceCapabilities.UINumber = -1; - - Stack.Parameters.DeviceCapabilities.Capabilities = &DeviceCapabilities; - Status = IopInitiatePnpIrp( - DeviceNode->PhysicalDeviceObject, - &IoStatusBlock, - IRP_MN_QUERY_CAPABILITIES, - &Stack); - if (NT_SUCCESS(Status)) - { - } - else - { - DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); - } - - DeviceNode->CapabilityFlags = *(PULONG)((ULONG_PTR)&DeviceCapabilities + 4); - DeviceNode->Address = DeviceCapabilities.Address; - - if (!DeviceCapabilities.UniqueID) - { - DPRINT("Instance ID is not unique\n"); - /* FIXME: Add information from parent bus driver to InstancePath */ - } - - if (!IopCreateUnicodeString(&DeviceNode->InstancePath, InstancePath, PagedPool)) + if (!RtlCreateUnicodeString(&DeviceNode->InstancePath, InstancePath)) { DPRINT("No resources\n"); /* FIXME: Cleanup and disable device */ @@ -1415,20 +1805,16 @@ IopActionInterrogateDeviceStack( DeviceNode->ChildBusNumber = BusInformation->BusNumber; DeviceNode->ChildInterfaceType = BusInformation->LegacyBusType; - memcpy(&DeviceNode->BusTypeGuid, - &BusInformation->BusTypeGuid, - sizeof(GUID)); + DeviceNode->ChildBusTypeIndex = IopGetBusTypeGuidIndex(&BusInformation->BusTypeGuid); ExFreePool(BusInformation); } else { DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); - DeviceNode->ChildBusNumber = -1; - DeviceNode->ChildInterfaceType = -1; - memset(&DeviceNode->BusTypeGuid, - 0, - sizeof(GUID)); + DeviceNode->ChildBusNumber = 0xFFFFFFF0; + DeviceNode->ChildInterfaceType = InterfaceTypeUndefined; + DeviceNode->ChildBusTypeIndex = -1; } DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n"); @@ -1660,7 +2046,7 @@ IopActionInitChildServices( !IopDeviceNodeHasFlag(DeviceNode, DNF_ADDED) && !IopDeviceNodeHasFlag(DeviceNode, DNF_STARTED)) { - PMODULE_OBJECT ModuleObject; + PLDR_DATA_TABLE_ENTRY ModuleObject; PDRIVER_OBJECT DriverObject; Status = IopLoadServiceModule(&DeviceNode->ServiceName, &ModuleObject); @@ -1778,7 +2164,8 @@ IopInitializePnpServices( DeviceNode, IopActionInitBootServices, DeviceNode); - } else + } + else { IopInitDeviceTreeTraverseContext( &Context, @@ -1808,7 +2195,7 @@ IopInvalidateDeviceRelations( NTSTATUS Status; ULONG i; - DPRINT("DeviceNode %x\n", DeviceNode); + DPRINT("DeviceNode 0x%p\n", DeviceNode); DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n"); @@ -1941,6 +2328,38 @@ IopInvalidateDeviceRelations( } +static NTSTATUS INIT_FUNCTION +IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode) +{ +#if 0 + PWSTR KeyBuffer; + HANDLE InstanceKey = NULL; + NTSTATUS Status; + + /* Create registry key for the instance id, if it doesn't exist yet */ + KeyBuffer = ExAllocatePool(PagedPool, + (49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length); + wcscpy(KeyBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); + wcscat(KeyBuffer, DeviceNode->InstancePath.Buffer); + Status = IopCreateDeviceKeyPath(KeyBuffer, + &InstanceKey); + ExFreePool(KeyBuffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to create the instance key! (Status %lx)\n", Status); + return Status; + } + + /* FIXME: Set 'ConfigFlags' value */ + + ZwClose(InstanceKey); + + return Status; +#endif + return STATUS_SUCCESS; +} + + VOID INIT_FUNCTION PnpInit(VOID) { @@ -1951,6 +2370,11 @@ PnpInit(VOID) KeInitializeSpinLock(&IopDeviceTreeLock); + /* Initialize the Bus Type GUID List */ + IopBusTypeGuidList = ExAllocatePool(PagedPool, sizeof(IO_BUS_TYPE_GUID_LIST)); + RtlZeroMemory(IopBusTypeGuidList, sizeof(IO_BUS_TYPE_GUID_LIST)); + ExInitializeFastMutex(&IopBusTypeGuidList->Lock); + /* Initialize PnP-Event notification support */ Status = IopInitPlugPlayEvents(); if (!NT_SUCCESS(Status)) @@ -1985,9 +2409,8 @@ PnpInit(VOID) KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0); } - if (!IopCreateUnicodeString(&IopRootDeviceNode->InstancePath, - L"HTREE\\Root\\0", - PagedPool)) + if (!RtlCreateUnicodeString(&IopRootDeviceNode->InstancePath, + L"HTREE\\ROOT\\0")) { CPRINT("Failed to create the instance path!\n"); KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, STATUS_UNSUCCESSFUL, 0, 0, 0); @@ -2004,4 +2427,19 @@ PnpInit(VOID) IopRootDeviceNode->PhysicalDeviceObject); } + +VOID INIT_FUNCTION +PnpInit2(VOID) +{ + NTSTATUS Status; + + /* Set root device instance data */ + Status = IopSetRootDeviceInstanceData(IopRootDeviceNode); + if (!NT_SUCCESS(Status)) + { + CPRINT("Failed to set instance data\n"); + KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0); + } +} + /* EOF */