From 76ec8411a44bd44a0c5559fefc5e1b4dd3fed66b Mon Sep 17 00:00:00 2001 From: Dmitry Borisov Date: Fri, 3 May 2024 20:39:26 +0600 Subject: [PATCH] [ISAPNP] Fix parsing of complex resource data - Properly handle the case when the dependent function is placed after fixed resources - Initialize the version and revision fields of resource lists - Improve validation of resource data - Add more debug prints CORE-18562 --- drivers/bus/isapnp/hardware.c | 395 +++++++-------- drivers/bus/isapnp/isapnp.c | 849 +++++++++++++-------------------- drivers/bus/isapnp/isapnp.h | 13 +- drivers/bus/isapnp/isapnpres.h | 95 ++-- drivers/bus/isapnp/pdo.c | 24 +- 5 files changed, 551 insertions(+), 825 deletions(-) diff --git a/drivers/bus/isapnp/hardware.c b/drivers/bus/isapnp/hardware.c index 135ab574a16..937923959a3 100644 --- a/drivers/bus/isapnp/hardware.c +++ b/drivers/bus/isapnp/hardware.c @@ -20,13 +20,6 @@ #endif /* UNIT_TEST */ -typedef enum -{ - dfNotStarted, - dfStarted, - dfDone -} DEPEDENT_FUNCTION_STATE; - static inline VOID @@ -390,24 +383,6 @@ Peek( } } -static -CODE_SEG("PAGE") -VOID -PeekCached( - _In_reads_bytes_(Length) PUCHAR ResourceData, - _Out_writes_bytes_all_(Length) PVOID Buffer, - _In_ USHORT Length) -{ - PUCHAR Dest = Buffer; - - PAGED_CODE(); - - while (Length--) - { - *Dest++ = *ResourceData++; - } -} - static CODE_SEG("PAGE") UCHAR @@ -454,19 +429,28 @@ ReadTags( _In_ PUCHAR ReadDataPort, _Out_writes_(ISAPNP_MAX_RESOURCEDATA) PUCHAR Buffer, _In_ ULONG MaxLength, - _Out_ PUSHORT MaxLogDev) + _Out_ PUSHORT MaxLogDev, + _Out_ PULONG MaxTagsPerDevice) { + ULONG TagCount = 0; + PAGED_CODE(); *MaxLogDev = 0; + *MaxTagsPerDevice = 0; while (TRUE) { UCHAR Tag; USHORT TagLen; + ++TagCount; + if (MaxLength < 1) + { + DPRINT("Too small tag\n"); return STATUS_BUFFER_OVERFLOW; + } Tag = PeekByte(ReadDataPort); if (Tag == 0) @@ -487,7 +471,10 @@ ReadTags( UCHAR Temp[2]; if (MaxLength < sizeof(Temp)) + { + DPRINT("Too small tag\n"); return STATUS_BUFFER_OVERFLOW; + } Peek(ReadDataPort, &Temp, sizeof(Temp)); *Buffer++ = Temp[0]; @@ -505,17 +492,28 @@ ReadTags( } if (TagLen > MaxLength) + { + DPRINT("Too large resource data structure\n"); return STATUS_BUFFER_OVERFLOW; + } Peek(ReadDataPort, Buffer, TagLen); MaxLength -= TagLen; Buffer += TagLen; if (Tag == ISAPNP_TAG_LOGDEVID) - (*MaxLogDev)++; + { + /* Attempt to guess the allocation size based on the tags available */ + *MaxTagsPerDevice = max(*MaxTagsPerDevice, TagCount); + TagCount = 0; - if (Tag == ISAPNP_TAG_END) + (*MaxLogDev)++; + } + else if (Tag == ISAPNP_TAG_END) + { + *MaxTagsPerDevice = max(*MaxTagsPerDevice, TagCount); break; + } } return STATUS_SUCCESS; @@ -534,8 +532,8 @@ FreeLogicalDevice( if (LogDevice->FriendlyName) ExFreePoolWithTag(LogDevice->FriendlyName, TAG_ISAPNP); - if (LogDevice->Alternatives) - ExFreePoolWithTag(LogDevice->Alternatives, TAG_ISAPNP); + if (LogDevice->Resources) + ExFreePoolWithTag(LogDevice->Resources, TAG_ISAPNP); Entry = LogDevice->CompatibleIdList.Flink; while (Entry != &LogDevice->CompatibleIdList) @@ -562,15 +560,10 @@ ParseTags( _Inout_ PISAPNP_LOGICAL_DEVICE LogDevice) { USHORT LogDev; - DEPEDENT_FUNCTION_STATE DfState = dfNotStarted; + ISAPNP_DEPENDENT_FUNCTION_STATE DfState = dfNotStarted; + PISAPNP_RESOURCE Resource = LogDevice->Resources; PUCHAR IdStrPos = NULL; USHORT IdStrLen = 0; - UCHAR NumberOfIo = 0, - NumberOfIrq = 0, - NumberOfDma = 0, - NumberOfMemRange = 0, - NumberOfMemRange32 = 0, - NumberOfDepedentSet = 0; PAGED_CODE(); @@ -613,7 +606,7 @@ ParseTags( goto SkipTag; } - PeekCached(ResourceData, &Temp, TagLen); + RtlCopyMemory(&Temp, ResourceData, TagLen); ResourceData += TagLen; DPRINT("Found tag 0x%X (len %u)\n" @@ -643,7 +636,7 @@ ParseTags( if (!CompatibleId) return STATUS_INSUFFICIENT_RESOURCES; - PeekCached(ResourceData, &Temp, TagLen); + RtlCopyMemory(&Temp, ResourceData, TagLen); ResourceData += TagLen; DPRINT("Found tag 0x%X (len %u)\n" @@ -665,30 +658,21 @@ ParseTags( { PISAPNP_IRQ_DESCRIPTION Description; - if (LogDev != 0 || - (TagLen > sizeof(ISAPNP_IRQ_DESCRIPTION) || - TagLen < (sizeof(ISAPNP_IRQ_DESCRIPTION) - 1)) || - NumberOfIrq >= RTL_NUMBER_OF(LogDevice->Irq)) - { + if (LogDev != 0) goto SkipTag; - } - if (DfState == dfStarted) + if (TagLen > sizeof(ISAPNP_IRQ_DESCRIPTION) || + TagLen < (sizeof(ISAPNP_IRQ_DESCRIPTION) - 1)) { - if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) - goto SkipTag; - - Description = &LogDevice->Alternatives->Irq[NumberOfDepedentSet]; - } - else - { - Description = &LogDevice->Irq[NumberOfIrq].Description; - - LogDevice->Irq[NumberOfIrq].Index = NumberOfIrq; - ++NumberOfIrq; + DPRINT1("Invalid tag %x\n", ISAPNP_TAG_IRQ); + return STATUS_UNSUCCESSFUL; } - PeekCached(ResourceData, Description, TagLen); + Resource->Type = ISAPNP_RESOURCE_TYPE_IRQ; + Description = &Resource->IrqDescription; + ++Resource; + + RtlCopyMemory(Description, ResourceData, TagLen); ResourceData += TagLen; if (TagLen == (sizeof(ISAPNP_IRQ_DESCRIPTION) - 1)) @@ -708,28 +692,20 @@ ParseTags( { PISAPNP_DMA_DESCRIPTION Description; - if (LogDev != 0 || TagLen != sizeof(ISAPNP_DMA_DESCRIPTION) || - NumberOfDma >= RTL_NUMBER_OF(LogDevice->Dma)) - { + if (LogDev != 0) goto SkipTag; - } - if (DfState == dfStarted) + if (TagLen != sizeof(ISAPNP_DMA_DESCRIPTION)) { - if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) - goto SkipTag; - - Description = &LogDevice->Alternatives->Dma[NumberOfDepedentSet]; - } - else - { - Description = &LogDevice->Dma[NumberOfDma].Description; - - LogDevice->Dma[NumberOfDma].Index = NumberOfDma; - ++NumberOfDma; + DPRINT1("Invalid tag %x\n", ISAPNP_TAG_DMA); + return STATUS_UNSUCCESSFUL; } - PeekCached(ResourceData, Description, TagLen); + Resource->Type = ISAPNP_RESOURCE_TYPE_DMA; + Description = &Resource->DmaDescription; + ++Resource; + + RtlCopyMemory(Description, ResourceData, TagLen); ResourceData += TagLen; DPRINT("Found tag 0x%X (len %u)\n" @@ -744,48 +720,39 @@ ParseTags( case ISAPNP_TAG_STARTDEP: { - if (LogDev != 0 || TagLen > 1 || - NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) - { + if (LogDev != 0) goto SkipTag; + + if (TagLen > 1) + { + DPRINT1("Invalid tag %x\n", ISAPNP_TAG_STARTDEP); + return STATUS_UNSUCCESSFUL; } if (DfState == dfNotStarted) { - LogDevice->Alternatives = ExAllocatePoolZero(PagedPool, - sizeof(ISAPNP_ALTERNATIVES), - TAG_ISAPNP); - if (!LogDevice->Alternatives) - return STATUS_INSUFFICIENT_RESOURCES; - DfState = dfStarted; } - else if (DfState == dfStarted) - { - ++NumberOfDepedentSet; - } - else + else if (DfState != dfStarted) { goto SkipTag; } - ++LogDevice->Alternatives->Count; + Resource->Type = ISAPNP_RESOURCE_TYPE_START_DEPENDENT; + ++Resource; if (TagLen != 1) { - LogDevice->Alternatives->Priority[NumberOfDepedentSet] = 1; + Resource->Priority = 1; } else { - PeekCached(ResourceData, - &LogDevice->Alternatives->Priority[NumberOfDepedentSet], - TagLen); + RtlCopyMemory(&Resource->Priority, ResourceData, TagLen); ResourceData += TagLen; } - DPRINT("*** Start depedent set %u, priority %u ***\n", - NumberOfDepedentSet, - LogDevice->Alternatives->Priority[NumberOfDepedentSet]); + DPRINT("*** Start dependent set, priority %u ***\n", + Resource->Priority); break; } @@ -795,22 +762,14 @@ ParseTags( if (LogDev != 0 || DfState != dfStarted) goto SkipTag; + Resource->Type = ISAPNP_RESOURCE_TYPE_END_DEPENDENT; + ++Resource; + DfState = dfDone; ResourceData += TagLen; - if (HasIoAlternatives(LogDevice->Alternatives)) - LogDevice->Alternatives->IoIndex = NumberOfIo++; - if (HasIrqAlternatives(LogDevice->Alternatives)) - LogDevice->Alternatives->IrqIndex = NumberOfIrq++; - if (HasDmaAlternatives(LogDevice->Alternatives)) - LogDevice->Alternatives->DmaIndex = NumberOfDma++; - if (HasMemoryAlternatives(LogDevice->Alternatives)) - LogDevice->Alternatives->MemRangeIndex = NumberOfMemRange++; - if (HasMemory32Alternatives(LogDevice->Alternatives)) - LogDevice->Alternatives->MemRange32Index = NumberOfMemRange32++; - - DPRINT("*** End of depedent set ***\n"); + DPRINT("*** End of dependent set ***\n"); break; } @@ -819,28 +778,20 @@ ParseTags( { PISAPNP_IO_DESCRIPTION Description; - if (LogDev != 0 || TagLen != sizeof(ISAPNP_IO_DESCRIPTION) || - NumberOfIo >= RTL_NUMBER_OF(LogDevice->Io)) - { + if (LogDev != 0) goto SkipTag; - } - if (DfState == dfStarted) + if (TagLen != sizeof(ISAPNP_IO_DESCRIPTION)) { - if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) - goto SkipTag; - - Description = &LogDevice->Alternatives->Io[NumberOfDepedentSet]; - } - else - { - Description = &LogDevice->Io[NumberOfIo].Description; - - LogDevice->Io[NumberOfIo].Index = NumberOfIo; - ++NumberOfIo; + DPRINT1("Invalid tag %x\n", ISAPNP_TAG_IOPORT); + return STATUS_UNSUCCESSFUL; } - PeekCached(ResourceData, Description, TagLen); + Resource->Type = ISAPNP_RESOURCE_TYPE_IO; + Description = &Resource->IoDescription; + ++Resource; + + RtlCopyMemory(Description, ResourceData, TagLen); ResourceData += TagLen; DPRINT("Found tag 0x%X (len %u)\n" @@ -864,28 +815,20 @@ ParseTags( ISAPNP_FIXED_IO_DESCRIPTION Temp; PISAPNP_IO_DESCRIPTION Description; - if (LogDev != 0 || TagLen != sizeof(ISAPNP_FIXED_IO_DESCRIPTION) || - NumberOfIo >= RTL_NUMBER_OF(LogDevice->Io)) - { + if (LogDev != 0) goto SkipTag; - } - if (DfState == dfStarted) + if (TagLen != sizeof(ISAPNP_FIXED_IO_DESCRIPTION)) { - if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) - goto SkipTag; - - Description = &LogDevice->Alternatives->Io[NumberOfDepedentSet]; - } - else - { - Description = &LogDevice->Io[NumberOfIo].Description; - - LogDevice->Io[NumberOfIo].Index = NumberOfIo; - ++NumberOfIo; + DPRINT1("Invalid tag %x\n", ISAPNP_TAG_FIXEDIO); + return STATUS_UNSUCCESSFUL; } - PeekCached(ResourceData, &Temp, TagLen); + Resource->Type = ISAPNP_RESOURCE_TYPE_IO; + Description = &Resource->IoDescription; + ++Resource; + + RtlCopyMemory(&Temp, ResourceData, TagLen); ResourceData += TagLen; /* Save the address bits [0:9] */ @@ -919,7 +862,7 @@ ParseTags( if (!LogDevice->FriendlyName) return STATUS_INSUFFICIENT_RESOURCES; - PeekCached(IdStrPos, LogDevice->FriendlyName, IdStrLen); + RtlCopyMemory(LogDevice->FriendlyName, IdStrPos, IdStrLen); End = LogDevice->FriendlyName + IdStrLen - 1; while (End > LogDevice->FriendlyName && *End == ' ') @@ -929,6 +872,8 @@ ParseTags( *++End = ANSI_NULL; } + Resource->Type = ISAPNP_RESOURCE_TYPE_END; + return STATUS_SUCCESS; } @@ -936,28 +881,23 @@ ParseTags( { PISAPNP_MEMRANGE_DESCRIPTION Description; - if (LogDev != 0 || TagLen != sizeof(ISAPNP_MEMRANGE_DESCRIPTION) || - NumberOfMemRange >= RTL_NUMBER_OF(LogDevice->MemRange)) - { + if (LogDev != 0) goto SkipTag; - } - if (DfState == dfStarted) + if (TagLen != sizeof(ISAPNP_MEMRANGE_DESCRIPTION)) { - if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) - goto SkipTag; - - Description = &LogDevice->Alternatives->MemRange[NumberOfDepedentSet]; - } - else - { - Description = &LogDevice->MemRange[NumberOfMemRange].Description; - - LogDevice->MemRange[NumberOfMemRange].Index = NumberOfMemRange; - ++NumberOfMemRange; + DPRINT1("Invalid tag %x\n", ISAPNP_TAG_MEMRANGE); + return STATUS_UNSUCCESSFUL; } - PeekCached(ResourceData, Description, TagLen); + LogDevice->Flags |= ISAPNP_HAS_MEM24_DECODER; + ASSERT(!(LogDevice->Flags & ISAPNP_HAS_MEM32_DECODER)); + + Resource->Type = ISAPNP_RESOURCE_TYPE_MEMRANGE; + Description = &Resource->MemRangeDescription; + ++Resource; + + RtlCopyMemory(Description, ResourceData, TagLen); ResourceData += TagLen; DPRINT("Found tag 0x%X (len %u)\n" @@ -1004,28 +944,23 @@ ParseTags( { PISAPNP_MEMRANGE32_DESCRIPTION Description; - if (LogDev != 0 || TagLen != sizeof(ISAPNP_MEMRANGE32_DESCRIPTION) || - NumberOfMemRange32 >= RTL_NUMBER_OF(LogDevice->MemRange32)) - { + if (LogDev != 0) goto SkipTag; - } - if (DfState == dfStarted) + if (TagLen != sizeof(ISAPNP_MEMRANGE32_DESCRIPTION)) { - if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) - goto SkipTag; - - Description = &LogDevice->Alternatives->MemRange32[NumberOfDepedentSet]; - } - else - { - Description = &LogDevice->MemRange32[NumberOfMemRange32].Description; - - LogDevice->MemRange32[NumberOfMemRange32].Index = NumberOfMemRange32; - ++NumberOfMemRange32; + DPRINT1("Invalid tag %x\n", ISAPNP_TAG_MEM32RANGE); + return STATUS_UNSUCCESSFUL; } - PeekCached(ResourceData, Description, TagLen); + LogDevice->Flags |= ISAPNP_HAS_MEM32_DECODER; + ASSERT(!(LogDevice->Flags & ISAPNP_HAS_MEM24_DECODER)); + + Resource->Type = ISAPNP_RESOURCE_TYPE_MEMRANGE32; + Description = &Resource->MemRange32Description; + ++Resource; + + RtlCopyMemory(Description, ResourceData, TagLen); ResourceData += TagLen; DPRINT("Found tag 0x%X (len %u)\n" @@ -1049,28 +984,23 @@ ParseTags( ISAPNP_FIXEDMEMRANGE_DESCRIPTION Temp; PISAPNP_MEMRANGE32_DESCRIPTION Description; - if (LogDev != 0 || TagLen != sizeof(ISAPNP_FIXEDMEMRANGE_DESCRIPTION) || - NumberOfMemRange32 >= RTL_NUMBER_OF(LogDevice->MemRange32)) - { + if (LogDev != 0) goto SkipTag; - } - if (DfState == dfStarted) + if (TagLen != sizeof(ISAPNP_FIXEDMEMRANGE_DESCRIPTION)) { - if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) - goto SkipTag; - - Description = &LogDevice->Alternatives->MemRange32[NumberOfDepedentSet]; - } - else - { - Description = &LogDevice->MemRange32[NumberOfMemRange32].Description; - - LogDevice->MemRange32[NumberOfMemRange32].Index = NumberOfMemRange32; - ++NumberOfMemRange32; + DPRINT1("Invalid tag %x\n", ISAPNP_TAG_FIXEDMEM32RANGE); + return STATUS_UNSUCCESSFUL; } - PeekCached(ResourceData, &Temp, TagLen); + LogDevice->Flags |= ISAPNP_HAS_MEM32_DECODER; + ASSERT(!(LogDevice->Flags & ISAPNP_HAS_MEM24_DECODER)); + + Resource->Type = ISAPNP_RESOURCE_TYPE_MEMRANGE32; + Description = &Resource->MemRange32Description; + ++Resource; + + RtlCopyMemory(&Temp, ResourceData, TagLen); ResourceData += TagLen; Description->Information = Temp.Information; @@ -1121,7 +1051,7 @@ ReadCurrentResources( WriteLogicalDeviceNumber(LogDevice->LDN); - /* If the device is not activated by BIOS we just report a NULL resource list */ + /* If the device is not activated by BIOS then the device has no boot resources */ if (!(ReadByte(ReadDataPort, ISAPNP_ACTIVATE) & 1)) { LogDevice->Flags &= ~ISAPNP_HAS_RESOURCES; @@ -1217,7 +1147,6 @@ WriteResources( for (i = 0; i < PartialResourceList->Count; i++) { PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &PartialResourceList->PartialDescriptors[i]; - UCHAR Index; switch (Descriptor->Type) { @@ -1229,10 +1158,9 @@ WriteResources( Descriptor->u.Port.Start.LowPart + Descriptor->u.Port.Length - 1, NULL, - NULL, - &Index); + NULL); - WriteWord(ISAPNP_IOBASE(Index), (USHORT)Descriptor->u.Port.Start.LowPart); + WriteWord(ISAPNP_IOBASE(NumberOfIo), (USHORT)Descriptor->u.Port.Start.LowPart); ++NumberOfIo; break; @@ -1240,10 +1168,10 @@ WriteResources( case CmResourceTypeInterrupt: { - (VOID)FindIrqDescriptor(LogDevice, Descriptor->u.Interrupt.Level, &Index); + (VOID)FindIrqDescriptor(LogDevice, Descriptor->u.Interrupt.Level); - WriteByte(ISAPNP_IRQNO(Index), (UCHAR)Descriptor->u.Interrupt.Level); - WriteByte(ISAPNP_IRQTYPE(Index), + WriteByte(ISAPNP_IRQNO(NumberOfIrq), (UCHAR)Descriptor->u.Interrupt.Level); + WriteByte(ISAPNP_IRQTYPE(NumberOfIrq), Descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED ? IRQTYPE_HIGH_EDGE : IRQTYPE_LOW_LEVEL); @@ -1253,9 +1181,9 @@ WriteResources( case CmResourceTypeDma: { - (VOID)FindDmaDescriptor(LogDevice, Descriptor->u.Dma.Channel, &Index); + (VOID)FindDmaDescriptor(LogDevice, Descriptor->u.Dma.Channel); - WriteByte(ISAPNP_DMACHANNEL(Index), (UCHAR)Descriptor->u.Dma.Channel); + WriteByte(ISAPNP_DMACHANNEL(NumberOfDma), (UCHAR)Descriptor->u.Dma.Channel); ++NumberOfDma; break; @@ -1263,7 +1191,6 @@ WriteResources( case CmResourceTypeMemory: { - BOOLEAN Memory32; UCHAR Information; UCHAR MemoryControl = MEMORY_USE_8_BIT_DECODER; @@ -1271,30 +1198,28 @@ WriteResources( Descriptor->u.Memory.Start.LowPart, Descriptor->u.Memory.Start.LowPart + Descriptor->u.Memory.Length - 1, - &Memory32, - &Information, - &Index); + &Information); - if (!Memory32) + if (LogicalDevice->Flags & ISAPNP_HAS_MEM24_DECODER) { if (Information & MEMRANGE_16_BIT_MEMORY_MASK) MemoryControl = MEMORY_USE_16_BIT_DECODER; - WriteWord(ISAPNP_MEMBASE(Index), + WriteWord(ISAPNP_MEMBASE(NumberOfMemory), (USHORT)(Descriptor->u.Memory.Start.LowPart >> 8)); - if (ReadMemoryControl(ReadDataPort, Index) & MEMORY_UPPER_LIMIT) + if (ReadMemoryControl(ReadDataPort, NumberOfMemory) & MEMORY_UPPER_LIMIT) { - WriteByte(ISAPNP_MEMCONTROL(Index), + WriteByte(ISAPNP_MEMCONTROL(NumberOfMemory), MemoryControl | MEMORY_UPPER_LIMIT); - WriteWord(ISAPNP_MEMLIMIT(Index), + WriteWord(ISAPNP_MEMLIMIT(NumberOfMemory), (USHORT)((Descriptor->u.Memory.Start.LowPart + Descriptor->u.Memory.Length) >> 8)); } else { - WriteByte(ISAPNP_MEMCONTROL(Index), MemoryControl); - WriteWord(ISAPNP_MEMLIMIT(Index), + WriteByte(ISAPNP_MEMCONTROL(NumberOfMemory), MemoryControl); + WriteWord(ISAPNP_MEMLIMIT(NumberOfMemory), (USHORT)(LENGTH_TO_RANGE_LENGTH(Descriptor-> u.Memory.Length) >> 8)); } @@ -1303,7 +1228,7 @@ WriteResources( } else { - WriteDoubleWord(ISAPNP_MEMBASE32(Index), + WriteDoubleWord(ISAPNP_MEMBASE32(NumberOfMemory32), Descriptor->u.Memory.Start.LowPart); if ((Information & MEMRANGE_16_BIT_MEMORY_MASK) == MEMRANGE_32_BIT_MEMORY_ONLY) @@ -1311,18 +1236,18 @@ WriteResources( else if (Information & MEMRANGE_16_BIT_MEMORY_MASK) MemoryControl = MEMORY_USE_16_BIT_DECODER; - if (ReadMemoryControl32(ReadDataPort, Index) & MEMORY_UPPER_LIMIT) + if (ReadMemoryControl32(ReadDataPort, NumberOfMemory32) & MEMORY_UPPER_LIMIT) { - WriteByte(ISAPNP_MEMCONTROL32(Index), + WriteByte(ISAPNP_MEMCONTROL32(NumberOfMemory32), MemoryControl | MEMORY_UPPER_LIMIT); - WriteDoubleWord(ISAPNP_MEMLIMIT32(Index), + WriteDoubleWord(ISAPNP_MEMLIMIT32(NumberOfMemory32), Descriptor->u.Memory.Start.LowPart + Descriptor->u.Memory.Length); } else { - WriteByte(ISAPNP_MEMCONTROL32(Index), MemoryControl); - WriteDoubleWord(ISAPNP_MEMLIMIT32(Index), + WriteByte(ISAPNP_MEMCONTROL32(NumberOfMemory32), MemoryControl); + WriteDoubleWord(ISAPNP_MEMLIMIT32(NumberOfMemory32), LENGTH_TO_RANGE_LENGTH(Descriptor->u.Memory.Length)); } @@ -1501,6 +1426,7 @@ IsaHwFillDeviceList( NTSTATUS Status; UCHAR TempId[3], LogDev; ISAPNP_IDENTIFIER Identifier; + ULONG MaxTagsPerDevice; USHORT MaxLogDev; Wake(Csn); @@ -1510,7 +1436,11 @@ IsaHwFillDeviceList( IsaPnpExtractAscii(TempId, Identifier.VendorId); Identifier.ProdId = RtlUshortByteSwap(Identifier.ProdId); - Status = ReadTags(FdoExt->ReadDataPort, ResourceData, ISAPNP_MAX_RESOURCEDATA, &MaxLogDev); + Status = ReadTags(FdoExt->ReadDataPort, + ResourceData, + ISAPNP_MAX_RESOURCEDATA, + &MaxLogDev, + &MaxTagsPerDevice); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to read tags with status 0x%08lx, CSN %u\n", Status, Csn); @@ -1572,6 +1502,16 @@ IsaHwFillDeviceList( LogDevice->CSN = Csn; LogDevice->LDN = LogDev; + LogDevice->Resources = ExAllocatePoolWithTag(PagedPool, + MaxTagsPerDevice * sizeof(ISAPNP_RESOURCE), + TAG_ISAPNP); + if (!LogDevice->Resources) + { + DPRINT1("Failed to allocate the resources array\n"); + FreeLogicalDevice(LogDevice); + goto Deactivate; + } + Status = ParseTags(ResourceData, LogDev, LogDevice); if (!NT_SUCCESS(Status)) { @@ -1644,7 +1584,6 @@ IsaHwConfigureDevice( Descriptor->u.Port.Start.LowPart + Descriptor->u.Port.Length - 1, NULL, - NULL, NULL)) { return STATUS_RESOURCE_DATA_NOT_FOUND; @@ -1658,7 +1597,7 @@ IsaHwConfigureDevice( if (++NumberOfIrq > RTL_NUMBER_OF(LogicalDevice->Irq)) return STATUS_INVALID_PARAMETER_2; - if (!FindIrqDescriptor(LogicalDevice, Descriptor->u.Interrupt.Level, NULL)) + if (!FindIrqDescriptor(LogicalDevice, Descriptor->u.Interrupt.Level)) return STATUS_RESOURCE_DATA_NOT_FOUND; break; @@ -1669,7 +1608,7 @@ IsaHwConfigureDevice( if (++NumberOfDma > RTL_NUMBER_OF(LogicalDevice->Dma)) return STATUS_INVALID_PARAMETER_3; - if (!FindDmaDescriptor(LogicalDevice, Descriptor->u.Dma.Channel, NULL)) + if (!FindDmaDescriptor(LogicalDevice, Descriptor->u.Dma.Channel)) return STATUS_RESOURCE_DATA_NOT_FOUND; break; @@ -1686,14 +1625,12 @@ IsaHwConfigureDevice( Descriptor->u.Memory.Start.LowPart, Descriptor->u.Memory.Start.LowPart + Descriptor->u.Memory.Length - 1, - &Memory32, - NULL, NULL)) { return STATUS_RESOURCE_DATA_NOT_FOUND; } - if (!Memory32 && (Descriptor->u.Memory.Start.LowPart & 0xFF)) + if ((LogicalDevice->Flags & ISAPNP_HAS_MEM24_DECODER) && (Descriptor->u.Memory.Start.LowPart & 0xFF)) return STATUS_INVALID_PARAMETER; break; diff --git a/drivers/bus/isapnp/isapnp.c b/drivers/bus/isapnp/isapnp.c index 7126166b092..bf5b6cde8c8 100644 --- a/drivers/bus/isapnp/isapnp.c +++ b/drivers/bus/isapnp/isapnp.c @@ -10,12 +10,8 @@ /* INCLUDES *******************************************************************/ #ifndef UNIT_TEST + #include "isapnp.h" -#endif /* UNIT_TEST */ - -#include - -#ifndef UNIT_TEST #define NDEBUG #include @@ -32,46 +28,8 @@ LIST_ENTRY BusListHead; #endif /* UNIT_TEST */ -static PUCHAR Priority; - /* FUNCTIONS ******************************************************************/ -static -CODE_SEG("PAGE") -int -__cdecl -IsaComparePriority( - const void *A, - const void *B) -{ - PAGED_CODE(); - - return Priority[*(PUCHAR)A] - Priority[*(PUCHAR)B]; -} - -static -CODE_SEG("PAGE") -VOID -IsaDetermineBestConfig( - _Out_writes_all_(ISAPNP_MAX_ALTERNATIVES) PUCHAR BestConfig, - _In_ PISAPNP_ALTERNATIVES Alternatives) -{ - UCHAR i; - - PAGED_CODE(); - - for (i = 0; i < ISAPNP_MAX_ALTERNATIVES; i++) - { - BestConfig[i] = i; - } - - Priority = Alternatives->Priority; - qsort(BestConfig, - Alternatives->Count, - sizeof(*BestConfig), - IsaComparePriority); -} - static CODE_SEG("PAGE") VOID @@ -194,323 +152,298 @@ IsaConvertMemRange32Requirement( Description->Length - 1; } +/* + * For example, the PnP ROM + * 0x15, 0x04, ... // Logical device ID + * 0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x04, 0x04, // IO 330, len 4, align 4 + * 0x30, // **** Start DF **** + * 0x22, 0x04, 0x00, // IRQ 2 + * 0x31, 0x02, // **** Start DF **** + * 0x22, 0xC0, 0x00, // IRQ 6 or 7 + * 0x38, // **** End DF ****** + * 0x2A, 0x20, 0x3A, // DMA 5 + * 0x22, 0x00, 0x08, // IRQ 12 + * 0x79, 0x00, // END + * + * becomes the following resource requirements list: + * Interface 1 Bus 0 Slot 0 AlternativeLists 2 + * + * AltList #0, AltList->Count 4 + * [Option 0, ShareDisposition 1, Flags 11] IO: Min 0:330, Max 0:333, Align 4 Len 4 + * [Option 0, ShareDisposition 1, Flags 1] INT: Min 2 Max 2 + * [Option 0, ShareDisposition 0, Flags 0] DMA: Min 5 Max 5 + * [Option 0, ShareDisposition 1, Flags 1] INT: Min B Max B + * + * AltList #1, AltList->Count 5 + * [Option 0, ShareDisposition 1, Flags 11] IO: Min 0:330, Max 0:333, Align 4 Len 4 + * [Option 0, ShareDisposition 1, Flags 1] INT: Min 6 Max 6 + * [Option 8, ShareDisposition 1, Flags 1] INT: Min 7 Max 7 + * [Option 0, ShareDisposition 0, Flags 0] DMA: Min 5 Max 5 + * [Option 0, ShareDisposition 1, Flags 1] INT: Min B Max B + */ static CODE_SEG("PAGE") NTSTATUS IsaPnpCreateLogicalDeviceRequirements( _In_ PISAPNP_PDO_EXTENSION PdoExt) { - PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice; - RTL_BITMAP TempBitmap; - ULONG TempBuffer; - ULONG ResourceCount = 0, AltCount = 0, AltOptionalCount = 0; - ULONG ListSize, i, j; - BOOLEAN FirstDescriptor; PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; PIO_RESOURCE_DESCRIPTOR Descriptor; - PISAPNP_ALTERNATIVES Alternatives = LogDev->Alternatives; + ISAPNP_DEPENDENT_FUNCTION_STATE DfState; + ULONG FirstFixedDescriptors, LastFixedDescriptors; + ULONG ResourceCount, AltListCount, ListSize, i; + BOOLEAN IsFirstAltList, IsFirstDescriptor; + PIO_RESOURCE_LIST AltList; + PISAPNP_RESOURCE Resource; PAGED_CODE(); - /* Count number of requirements */ - for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) + /* Count the number of requirements */ + DfState = dfNotStarted; + FirstFixedDescriptors = 0; + LastFixedDescriptors = 0; + ResourceCount = 0; + AltListCount = 1; + Resource = PdoExt->IsaPnpDevice->Resources; + while (Resource->Type != ISAPNP_RESOURCE_TYPE_END) { - /* - * Use the continue statement to count the number of requirements. - * We handle a possible gap because depedent function can appear at - * any position in the logical device's requirements list. - */ - if (!LogDev->Io[i].Description.Length) - continue; - - ResourceCount++; - } - for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) - { - if (!LogDev->Irq[i].Description.Mask) - continue; - - TempBuffer = LogDev->Irq[i].Description.Mask; - RtlInitializeBitMap(&TempBitmap, - &TempBuffer, - RTL_BITS_OF(LogDev->Irq[i].Description.Mask)); - ResourceCount += RtlNumberOfSetBits(&TempBitmap); - } - for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++) - { - if (!LogDev->Dma[i].Description.Mask) - continue; - - TempBuffer = LogDev->Dma[i].Description.Mask; - RtlInitializeBitMap(&TempBitmap, - &TempBuffer, - RTL_BITS_OF(LogDev->Dma[i].Description.Mask)); - ResourceCount += RtlNumberOfSetBits(&TempBitmap); - } - for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++) - { - if (!LogDev->MemRange[i].Description.Length) - continue; - - ResourceCount++; - } - for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++) - { - if (!LogDev->MemRange32[i].Description.Length) - continue; - - ResourceCount++; - } - if (Alternatives) - { - ULONG BitCount; - - if (HasIoAlternatives(Alternatives)) - AltCount++; - if (HasIrqAlternatives(Alternatives)) - AltCount++; - if (HasDmaAlternatives(Alternatives)) - AltCount++; - if (HasMemoryAlternatives(Alternatives)) - AltCount++; - if (HasMemory32Alternatives(Alternatives)) - AltCount++; - ResourceCount += AltCount; - - if (HasIrqAlternatives(Alternatives)) + switch (Resource->Type) { - for (i = 0; i < Alternatives->Count; i++) + case ISAPNP_RESOURCE_TYPE_START_DEPENDENT: { - TempBuffer = Alternatives->Irq[i].Mask; - RtlInitializeBitMap(&TempBitmap, - &TempBuffer, - RTL_BITS_OF(Alternatives->Irq[i].Mask)); - BitCount = RtlNumberOfSetBits(&TempBitmap); + if (DfState == dfStarted) + ++AltListCount; - if (BitCount > 1) - AltOptionalCount += BitCount - 1; + DfState = dfStarted; + break; } - } - if (HasDmaAlternatives(Alternatives)) - { - for (i = 0; i < Alternatives->Count; i++) + + case ISAPNP_RESOURCE_TYPE_END_DEPENDENT: { - TempBuffer = Alternatives->Dma[i].Mask; - RtlInitializeBitMap(&TempBitmap, - &TempBuffer, - RTL_BITS_OF(Alternatives->Dma[i].Mask)); - BitCount = RtlNumberOfSetBits(&TempBitmap); - - if (BitCount > 1) - AltOptionalCount += BitCount - 1; + DfState = dfDone; + break; } + + case ISAPNP_RESOURCE_TYPE_IRQ: + case ISAPNP_RESOURCE_TYPE_DMA: + { + RTL_BITMAP ResourceBitmap; + ULONG BitmapSize, BitmapBuffer, BitCount; + + if (Resource->Type == ISAPNP_RESOURCE_TYPE_IRQ) + { + BitmapSize = RTL_BITS_OF(Resource->IrqDescription.Mask); + BitmapBuffer = Resource->IrqDescription.Mask; + } + else + { + BitmapSize = RTL_BITS_OF(Resource->DmaDescription.Mask); + BitmapBuffer = Resource->DmaDescription.Mask; + } + RtlInitializeBitMap(&ResourceBitmap, &BitmapBuffer, BitmapSize); + + BitCount = RtlNumberOfSetBits(&ResourceBitmap); + switch (DfState) + { + case dfNotStarted: + FirstFixedDescriptors += BitCount; + break; + + case dfStarted: + ResourceCount += BitCount; + break; + + case dfDone: + LastFixedDescriptors += BitCount; + break; + + DEFAULT_UNREACHABLE; + } + + break; + } + + case ISAPNP_RESOURCE_TYPE_IO: + case ISAPNP_RESOURCE_TYPE_MEMRANGE: + case ISAPNP_RESOURCE_TYPE_MEMRANGE32: + { + switch (DfState) + { + case dfNotStarted: + ++FirstFixedDescriptors; + break; + + case dfStarted: + ++ResourceCount; + break; + + case dfDone: + ++LastFixedDescriptors; + break; + + DEFAULT_UNREACHABLE; + } + break; + } + + default: + ASSERT(FALSE); + UNREACHABLE; + break; } + + ++Resource; } - if (ResourceCount == 0) + + /* This logical device has no resource requirements */ + if ((ResourceCount == 0) && (FirstFixedDescriptors == 0) && (LastFixedDescriptors == 0)) return STATUS_SUCCESS; /* Allocate memory to store requirements */ - ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST); - if (Alternatives) - { - ListSize += sizeof(IO_RESOURCE_DESCRIPTOR) * (ResourceCount - 1) * Alternatives->Count - + sizeof(IO_RESOURCE_LIST) * (Alternatives->Count - 1) - + sizeof(IO_RESOURCE_DESCRIPTOR) * AltOptionalCount; - } - else - { - ListSize += sizeof(IO_RESOURCE_DESCRIPTOR) * (ResourceCount - 1); - } + ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List) + + FIELD_OFFSET(IO_RESOURCE_LIST, Descriptors) * AltListCount + + sizeof(IO_RESOURCE_DESCRIPTOR) * ResourceCount + + sizeof(IO_RESOURCE_DESCRIPTOR) * AltListCount * + (FirstFixedDescriptors + LastFixedDescriptors); RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); if (!RequirementsList) return STATUS_NO_MEMORY; RequirementsList->ListSize = ListSize; RequirementsList->InterfaceType = Isa; - RequirementsList->AlternativeLists = Alternatives ? Alternatives->Count : 1; + RequirementsList->AlternativeLists = AltListCount; RequirementsList->List[0].Version = 1; RequirementsList->List[0].Revision = 1; - RequirementsList->List[0].Count = ResourceCount; /* Store requirements */ - Descriptor = RequirementsList->List[0].Descriptors; - for (i = 0; i < RTL_NUMBER_OF(LogDev->Io); i++) + IsFirstAltList = TRUE; + AltList = &RequirementsList->List[0]; + Descriptor = &RequirementsList->List[0].Descriptors[0]; + Resource = PdoExt->IsaPnpDevice->Resources; + while (Resource->Type != ISAPNP_RESOURCE_TYPE_END) { - if (!LogDev->Io[i].Description.Length) - break; - - IsaConvertIoRequirement(Descriptor++, &LogDev->Io[i].Description); - } - for (i = 0; i < RTL_NUMBER_OF(LogDev->Irq); i++) - { - if (!LogDev->Irq[i].Description.Mask) - continue; - - FirstDescriptor = TRUE; - - for (j = 0; j < RTL_BITS_OF(LogDev->Irq[i].Description.Mask); j++) + switch (Resource->Type) { - if (!(LogDev->Irq[i].Description.Mask & (1 << j))) - continue; - - IsaConvertIrqRequirement(Descriptor++, - &LogDev->Irq[i].Description, - j, - FirstDescriptor); - - if (FirstDescriptor) - FirstDescriptor = FALSE; - } - } - for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++) - { - if (!LogDev->Dma[i].Description.Mask) - continue; - - FirstDescriptor = TRUE; - - for (j = 0; j < RTL_BITS_OF(LogDev->Dma[i].Description.Mask); j++) - { - if (!(LogDev->Dma[i].Description.Mask & (1 << j))) - continue; - - IsaConvertDmaRequirement(Descriptor++, - &LogDev->Dma[i].Description, - j, - FirstDescriptor); - - if (FirstDescriptor) - FirstDescriptor = FALSE; - } - } - for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange); i++) - { - if (!LogDev->MemRange[i].Description.Length) - continue; - - IsaConvertMemRangeRequirement(Descriptor++, - &LogDev->MemRange[i].Description); - } - for (i = 0; i < RTL_NUMBER_OF(LogDev->MemRange32); i++) - { - if (!LogDev->MemRange32[i].Description.Length) - continue; - - IsaConvertMemRange32Requirement(Descriptor++, - &LogDev->MemRange32[i].Description); - } - if (Alternatives) - { - UCHAR BestConfig[ISAPNP_MAX_ALTERNATIVES]; - PIO_RESOURCE_LIST AltList = &RequirementsList->List[0]; - PIO_RESOURCE_LIST NextList = AltList; - - IsaDetermineBestConfig(BestConfig, Alternatives); - - for (i = 0; i < RequirementsList->AlternativeLists; i++) - { - RtlMoveMemory(NextList, AltList, sizeof(IO_RESOURCE_LIST)); - - /* Just because the 'NextList->Count++' correction */ - NextList->Count = ResourceCount; - /* - * For example, the ROM - * 0x15, ... // Logical device ID - * 0x30, // Start DF - * 0x22, 0x04, 0x00 // IRQ - * 0x30, // Start DF - * 0x22, 0xC0, 0x00 // IRQ - * 0x38, // End DF - * 0x2A, 0x20, 0x3A // DMA - * 0x22, 0x00, 0x08 // IRQ - * 0x79, 0x00 // END - * - * will be represented as the following resource requirements list: - * Interface 1 Bus 0 Slot 0 AlternativeLists 2 - * AltList 1, AltList->Count 3 - * [Option 0, ShareDisposition 1, Flags 1] INT: Min B Max B - * [Option 0, ShareDisposition 0, Flags 0] DMA: Min 5 Max 5 - * [Option 0, ShareDisposition 1, Flags 1] INT: Min 2 Max 2 - * End Descriptors - * AltList 2, AltList->Count 4 - * [Option 0, ShareDisposition 1, Flags 1] INT: Min B Max B - * [Option 0, ShareDisposition 0, Flags 0] DMA: Min 5 Max 5 - * [Option 0, ShareDisposition 1, Flags 1] INT: Min 6 Max 6 - * [Option 8, ShareDisposition 1, Flags 1] INT: Min 7 Max 7 - * End Descriptors - */ - - /* Propagate the fixed resources to our new list */ - for (j = 0; j < AltList->Count - AltCount; j++) + case ISAPNP_RESOURCE_TYPE_START_DEPENDENT: { - RtlMoveMemory(&NextList->Descriptors[j], - &AltList->Descriptors[j], - sizeof(IO_RESOURCE_DESCRIPTOR)); - } - - Descriptor = &NextList->Descriptors[NextList->Count - AltCount]; - - /* - * Append alternatives. - * NOTE: To keep it simple, we append these to the end of the list. - */ - if (HasIoAlternatives(Alternatives)) - { - IsaConvertIoRequirement(Descriptor++, - &Alternatives->Io[BestConfig[i]]); - } - if (HasIrqAlternatives(Alternatives)) - { - FirstDescriptor = TRUE; - - for (j = 0; j < RTL_BITS_OF(Alternatives->Irq[BestConfig[i]].Mask); j++) + if (!IsFirstAltList) { - if (!(Alternatives->Irq[BestConfig[i]].Mask & (1 << j))) + /* Add room for the fixed descriptors */ + AltList->Count += LastFixedDescriptors; + + /* Move on to the next list */ + AltList = (PIO_RESOURCE_LIST)(AltList->Descriptors + AltList->Count); + AltList->Version = 1; + AltList->Revision = 1; + + /* Propagate the fixed resources to our new list */ + RtlCopyMemory(&AltList->Descriptors, + RequirementsList->List[0].Descriptors, + sizeof(IO_RESOURCE_DESCRIPTOR) * FirstFixedDescriptors); + AltList->Count += FirstFixedDescriptors; + + Descriptor = &AltList->Descriptors[FirstFixedDescriptors]; + } + + IsFirstAltList = FALSE; + break; + } + + case ISAPNP_RESOURCE_TYPE_END_DEPENDENT: + break; + + case ISAPNP_RESOURCE_TYPE_IO: + { + IsaConvertIoRequirement(Descriptor++, &Resource->IoDescription); + + ++AltList->Count; + break; + } + + case ISAPNP_RESOURCE_TYPE_IRQ: + { + IsFirstDescriptor = TRUE; + + for (i = 0; i < RTL_BITS_OF(Resource->IrqDescription.Mask); i++) + { + if (!(Resource->IrqDescription.Mask & (1 << i))) continue; IsaConvertIrqRequirement(Descriptor++, - &Alternatives->Irq[BestConfig[i]], - j, - FirstDescriptor); + &Resource->IrqDescription, + i, + IsFirstDescriptor); + ++AltList->Count; - if (FirstDescriptor) - FirstDescriptor = FALSE; - else - NextList->Count++; + IsFirstDescriptor = FALSE; } - } - if (HasDmaAlternatives(Alternatives)) - { - FirstDescriptor = TRUE; - for (j = 0; j < RTL_BITS_OF(Alternatives->Dma[BestConfig[i]].Mask); j++) + break; + } + + case ISAPNP_RESOURCE_TYPE_DMA: + { + IsFirstDescriptor = TRUE; + + for (i = 0; i < RTL_BITS_OF(Resource->DmaDescription.Mask); i++) { - if (!(Alternatives->Dma[BestConfig[i]].Mask & (1 << j))) + if (!(Resource->DmaDescription.Mask & (1 << i))) continue; IsaConvertDmaRequirement(Descriptor++, - &Alternatives->Dma[BestConfig[i]], - j, - FirstDescriptor); + &Resource->DmaDescription, + i, + IsFirstDescriptor); + ++AltList->Count; - if (FirstDescriptor) - FirstDescriptor = FALSE; - else - NextList->Count++; + IsFirstDescriptor = FALSE; } + + break; } - if (HasMemoryAlternatives(Alternatives)) + + case ISAPNP_RESOURCE_TYPE_MEMRANGE: { - IsaConvertMemRangeRequirement(Descriptor++, - &Alternatives->MemRange[BestConfig[i]]); + IsaConvertMemRangeRequirement(Descriptor++, &Resource->MemRangeDescription); + + ++AltList->Count; + break; } - if (HasMemory32Alternatives(Alternatives)) + + case ISAPNP_RESOURCE_TYPE_MEMRANGE32: { - IsaConvertMemRange32Requirement(Descriptor++, - &Alternatives->MemRange32[BestConfig[i]]); + IsaConvertMemRange32Requirement(Descriptor++, &Resource->MemRange32Description); + + ++AltList->Count; + break; } + default: + ASSERT(FALSE); + UNREACHABLE; + break; + } + + ++Resource; + } + + /* Append the fixed resources */ + if (LastFixedDescriptors) + { + PIO_RESOURCE_LIST NextList = &RequirementsList->List[0]; + + /* Make the descriptor point to the fixed resources */ + Descriptor -= LastFixedDescriptors; + + /* Propagate the fixed resources onto previous lists */ + AltListCount = RequirementsList->AlternativeLists - 1; + for (i = 0; i < AltListCount; i++) + { + RtlCopyMemory(&NextList->Descriptors[NextList->Count - LastFixedDescriptors], + Descriptor, + sizeof(IO_RESOURCE_DESCRIPTOR) * LastFixedDescriptors); + NextList = (PIO_RESOURCE_LIST)(NextList->Descriptors + NextList->Count); } } @@ -527,58 +460,42 @@ FindIoDescriptor( _In_ ULONG RangeStart, _In_ ULONG RangeEnd, _Out_opt_ PUCHAR Information, - _Out_opt_ PULONG Length, - _Out_opt_ PUCHAR WriteOrder) + _Out_opt_ PULONG Length) { - ULONG i; - BOOLEAN Match; - PISAPNP_IO_DESCRIPTION Description; + PISAPNP_RESOURCE Resource; PAGED_CODE(); - for (i = 0; i < RTL_NUMBER_OF(LogDevice->Io); i++) + Resource = LogDevice->Resources; + while (Resource->Type != ISAPNP_RESOURCE_TYPE_END) { - Description = &LogDevice->Io[i].Description; - - Match = Base ? (Base >= Description->Minimum) && (Base <= Description->Maximum) - : (RangeStart >= Description->Minimum) && - (RangeEnd <= (ULONG)(Description->Maximum + Description->Length - 1)); - - if (Match) + if (Resource->Type == ISAPNP_RESOURCE_TYPE_IO) { - if (Information) - *Information = Description->Information; - if (Length) - *Length = Description->Length; - if (WriteOrder) - *WriteOrder = LogDevice->Io[i].Index; + PISAPNP_IO_DESCRIPTION Description = &Resource->IoDescription; + BOOLEAN Match; - return TRUE; + if (Base) + { + Match = (Base >= Description->Minimum) && (Base <= Description->Maximum); + } + else + { + Match = (RangeStart >= Description->Minimum) && + (RangeEnd <= (ULONG)(Description->Maximum + Description->Length - 1)); + } + + if (Match) + { + if (Information) + *Information = Description->Information; + if (Length) + *Length = Description->Length; + + return TRUE; + } } - } - if (!LogDevice->Alternatives) - return FALSE; - - for (i = 0; i < LogDevice->Alternatives->Count; i++) - { - Description = &LogDevice->Alternatives->Io[i]; - - Match = Base ? (Base >= Description->Minimum) && (Base <= Description->Maximum) - : (RangeStart >= Description->Minimum) && - (RangeEnd <= (ULONG)(Description->Maximum + Description->Length - 1)); - - if (Match) - { - if (Information) - *Information = Description->Information; - if (Length) - *Length = Description->Length; - if (WriteOrder) - *WriteOrder = LogDevice->Alternatives->IoIndex; - - return TRUE; - } + ++Resource; } return FALSE; @@ -588,53 +505,24 @@ CODE_SEG("PAGE") BOOLEAN FindIrqDescriptor( _In_ PISAPNP_LOGICAL_DEVICE LogDevice, - _In_ ULONG Vector, - _Out_opt_ PUCHAR WriteOrder) + _In_ ULONG Vector) { - ULONG i, j; - PISAPNP_IRQ_DESCRIPTION Description; + PISAPNP_RESOURCE Resource; PAGED_CODE(); - for (i = 0; i < RTL_NUMBER_OF(LogDevice->Irq); i++) + Resource = LogDevice->Resources; + while (Resource->Type != ISAPNP_RESOURCE_TYPE_END) { - Description = &LogDevice->Irq[i].Description; - - for (j = 0; j < RTL_BITS_OF(Description->Mask); j++) + if (Resource->Type == ISAPNP_RESOURCE_TYPE_IRQ) { - if (Description->Mask & (1 << j)) - { - if (j == Vector) - { - if (WriteOrder) - *WriteOrder = LogDevice->Irq[i].Index; + PISAPNP_IRQ_DESCRIPTION Description = &Resource->IrqDescription; - return TRUE; - } - } + if (Description->Mask & (1 << Vector)) + return TRUE; } - } - if (!LogDevice->Alternatives) - return FALSE; - - for (i = 0; i < LogDevice->Alternatives->Count; i++) - { - Description = &LogDevice->Alternatives->Irq[i]; - - for (j = 0; j < RTL_BITS_OF(Description->Mask); j++) - { - if (Description->Mask & (1 << j)) - { - if (j == Vector) - { - if (WriteOrder) - *WriteOrder = LogDevice->Alternatives->IrqIndex; - - return TRUE; - } - } - } + ++Resource; } return FALSE; @@ -644,53 +532,24 @@ CODE_SEG("PAGE") BOOLEAN FindDmaDescriptor( _In_ PISAPNP_LOGICAL_DEVICE LogDevice, - _In_ ULONG Channel, - _Out_opt_ PUCHAR WriteOrder) + _In_ ULONG Channel) { - ULONG i, j; - PISAPNP_DMA_DESCRIPTION Description; + PISAPNP_RESOURCE Resource; PAGED_CODE(); - for (i = 0; i < RTL_NUMBER_OF(LogDevice->Dma); i++) + Resource = LogDevice->Resources; + while (Resource->Type != ISAPNP_RESOURCE_TYPE_END) { - Description = &LogDevice->Dma[i].Description; - - for (j = 0; j < RTL_BITS_OF(Description->Mask); j++) + if (Resource->Type == ISAPNP_RESOURCE_TYPE_DMA) { - if (Description->Mask & (1 << j)) - { - if (j == Channel) - { - if (WriteOrder) - *WriteOrder = LogDevice->Dma[i].Index; + PISAPNP_DMA_DESCRIPTION Description = &Resource->DmaDescription; - return TRUE; - } - } + if (Description->Mask & (1 << Channel)) + return TRUE; } - } - if (!LogDevice->Alternatives) - return FALSE; - - for (i = 0; i < LogDevice->Alternatives->Count; i++) - { - Description = &LogDevice->Alternatives->Dma[i]; - - for (j = 0; j < RTL_BITS_OF(Description->Mask); j++) - { - if (Description->Mask & (1 << j)) - { - if (j == Channel) - { - if (WriteOrder) - *WriteOrder = LogDevice->Alternatives->DmaIndex; - - return TRUE; - } - } - } + ++Resource; } return FALSE; @@ -702,87 +561,57 @@ FindMemoryDescriptor( _In_ PISAPNP_LOGICAL_DEVICE LogDevice, _In_ ULONG RangeStart, _In_ ULONG RangeEnd, - _Out_opt_ PBOOLEAN Memory32, - _Out_opt_ PUCHAR Information, - _Out_opt_ PUCHAR WriteOrder) + _Out_opt_ PUCHAR Information) { - ULONG i; - PISAPNP_MEMRANGE_DESCRIPTION Description; - PISAPNP_MEMRANGE32_DESCRIPTION Description32; + PISAPNP_RESOURCE Resource; PAGED_CODE(); - for (i = 0; i < RTL_NUMBER_OF(LogDevice->MemRange); i++) + Resource = LogDevice->Resources; + while (Resource->Type != ISAPNP_RESOURCE_TYPE_END) { - Description = &LogDevice->MemRange[i].Description; - - if ((RangeStart >= (ULONG)(Description->Minimum << 8)) && - (RangeEnd <= (ULONG)((Description->Maximum << 8) + (Description->Length << 8) - 1))) + switch (Resource->Type) { - if (Memory32) - *Memory32 = FALSE; - if (Information) - *Information = Description->Information; - if (WriteOrder) - *WriteOrder = LogDevice->MemRange[i].Index; + case ISAPNP_RESOURCE_TYPE_MEMRANGE: + { + PISAPNP_MEMRANGE_DESCRIPTION Description; - return TRUE; + Description = &Resource->MemRangeDescription; + + if ((RangeStart >= (ULONG)(Description->Minimum << 8)) && + (RangeEnd <= (ULONG)((Description->Maximum << 8) + + (Description->Length << 8) - 1))) + { + if (Information) + *Information = Description->Information; + + return TRUE; + } + break; + } + + case ISAPNP_RESOURCE_TYPE_MEMRANGE32: + { + PISAPNP_MEMRANGE32_DESCRIPTION Description32; + + Description32 = &Resource->MemRange32Description; + + if ((RangeStart >= Description32->Minimum) && + (RangeEnd <= (Description32->Maximum + Description32->Length - 1))) + { + if (Information) + *Information = Description32->Information; + + return TRUE; + } + break; + } + + default: + break; } - } - for (i = 0; i < RTL_NUMBER_OF(LogDevice->MemRange32); i++) - { - Description32 = &LogDevice->MemRange32[i].Description; - if ((RangeStart >= Description32->Minimum) && - (RangeEnd <= (Description32->Maximum + Description32->Length - 1))) - { - if (Memory32) - *Memory32 = TRUE; - if (Information) - *Information = Description32->Information; - if (WriteOrder) - *WriteOrder = LogDevice->MemRange32[i].Index; - - return TRUE; - } - } - - if (!LogDevice->Alternatives) - return FALSE; - - for (i = 0; i < LogDevice->Alternatives->Count; i++) - { - Description = &LogDevice->Alternatives->MemRange[i]; - - if ((RangeStart >= (ULONG)(Description->Minimum << 8)) && - (RangeEnd <= (ULONG)((Description->Maximum << 8) + (Description->Length << 8) - 1))) - { - if (Memory32) - *Memory32 = FALSE; - if (Information) - *Information = Description->Information; - if (WriteOrder) - *WriteOrder = LogDevice->Alternatives->MemRangeIndex; - - return TRUE; - } - } - for (i = 0; i < LogDevice->Alternatives->Count; i++) - { - Description32 = &LogDevice->Alternatives->MemRange32[i]; - - if ((RangeStart >= Description32->Minimum) && - (RangeEnd <= (Description32->Maximum + Description32->Length - 1))) - { - if (Memory32) - *Memory32 = TRUE; - if (Information) - *Information = Description32->Information; - if (WriteOrder) - *WriteOrder = LogDevice->Alternatives->MemRange32Index; - - return TRUE; - } + ++Resource; } return FALSE; @@ -872,9 +701,9 @@ IsaPnpCreateLogicalDeviceResources( 0, 0, &Information, - &CurrentLength, - NULL)) + &CurrentLength)) { + DPRINT1("I/O entry #%lu %x not found\n", i, LogDev->Io[i].CurrentBase); goto InvalidBiosResources; } @@ -894,9 +723,6 @@ IsaPnpCreateLogicalDeviceResources( if (!LogDev->Irq[i].CurrentNo) break; - if (!FindIrqDescriptor(LogDev, LogDev->Irq[i].CurrentNo, NULL)) - goto InvalidBiosResources; - Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; Descriptor->Type = CmResourceTypeInterrupt; Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; @@ -906,16 +732,13 @@ IsaPnpCreateLogicalDeviceResources( Descriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; Descriptor->u.Interrupt.Level = LogDev->Irq[i].CurrentNo; Descriptor->u.Interrupt.Vector = LogDev->Irq[i].CurrentNo; - Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF; + Descriptor->u.Interrupt.Affinity = (KAFFINITY)-1; } for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++) { if (LogDev->Dma[i].CurrentChannel == 4) break; - if (!FindDmaDescriptor(LogDev, LogDev->Dma[i].CurrentChannel, NULL)) - goto InvalidBiosResources; - Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++]; Descriptor->Type = CmResourceTypeDma; Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; @@ -930,10 +753,12 @@ IsaPnpCreateLogicalDeviceResources( if (!FindMemoryDescriptor(LogDev, LogDev->MemRange[i].CurrentBase, LogDev->MemRange[i].CurrentLength, - NULL, - &Information, - NULL)) + &Information)) { + DPRINT1("MEM entry #%lu %lx %lx not found\n", + i, + LogDev->MemRange[i].CurrentBase, + LogDev->MemRange[i].CurrentLength); goto InvalidBiosResources; } @@ -956,10 +781,12 @@ IsaPnpCreateLogicalDeviceResources( if (!FindMemoryDescriptor(LogDev, LogDev->MemRange32[i].CurrentBase, LogDev->MemRange32[i].CurrentLength, - NULL, - &Information, - NULL)) + &Information)) { + DPRINT1("MEM32 entry #%lu %lx %lx not found\n", + i, + LogDev->MemRange32[i].CurrentBase, + LogDev->MemRange32[i].CurrentLength); goto InvalidBiosResources; } @@ -980,7 +807,7 @@ IsaPnpCreateLogicalDeviceResources( return STATUS_SUCCESS; InvalidBiosResources: - DPRINT("Invalid boot resources! (CSN %u, LDN %u)\n", LogDev->CSN, LogDev->LDN); + DPRINT1("Invalid boot resources! (CSN %u, LDN %u)\n", LogDev->CSN, LogDev->LDN); LogDev->Flags &= ~ISAPNP_HAS_RESOURCES; ExFreePoolWithTag(ResourceList, TAG_ISAPNP); diff --git a/drivers/bus/isapnp/isapnp.h b/drivers/bus/isapnp/isapnp.h index 17945dbe06a..998c7e766f0 100644 --- a/drivers/bus/isapnp/isapnp.h +++ b/drivers/bus/isapnp/isapnp.h @@ -151,22 +151,19 @@ FindIoDescriptor( _In_ ULONG RangeStart, _In_ ULONG RangeEnd, _Out_opt_ PUCHAR Information, - _Out_opt_ PULONG Length, - _Out_opt_ PUCHAR WriteOrder); + _Out_opt_ PULONG Length); CODE_SEG("PAGE") BOOLEAN FindIrqDescriptor( _In_ PISAPNP_LOGICAL_DEVICE LogDevice, - _In_ ULONG Vector, - _Out_opt_ PUCHAR WriteOrder); + _In_ ULONG Vector); CODE_SEG("PAGE") BOOLEAN FindDmaDescriptor( _In_ PISAPNP_LOGICAL_DEVICE LogDevice, - _In_ ULONG Channel, - _Out_opt_ PUCHAR WriteOrder); + _In_ ULONG Channel); CODE_SEG("PAGE") BOOLEAN @@ -174,9 +171,7 @@ FindMemoryDescriptor( _In_ PISAPNP_LOGICAL_DEVICE LogDevice, _In_ ULONG RangeStart, _In_ ULONG RangeEnd, - _Out_opt_ PBOOLEAN Memory32, - _Out_opt_ PUCHAR Information, - _Out_opt_ PUCHAR WriteOrder); + _Out_opt_ PUCHAR Information); CODE_SEG("PAGE") PIO_RESOURCE_REQUIREMENTS_LIST diff --git a/drivers/bus/isapnp/isapnpres.h b/drivers/bus/isapnp/isapnpres.h index 16c21646a0f..a21299a1710 100644 --- a/drivers/bus/isapnp/isapnpres.h +++ b/drivers/bus/isapnp/isapnpres.h @@ -9,10 +9,7 @@ #pragma once /** @brief Maximum size of resource data structure supported by the driver. */ -#define ISAPNP_MAX_RESOURCEDATA 0x1000 - -/** @brief Maximum number of Start DF tags supported by the driver. */ -#define ISAPNP_MAX_ALTERNATIVES 8 +#define ISAPNP_MAX_RESOURCEDATA 0x1000 typedef struct _ISAPNP_IO { @@ -59,23 +56,35 @@ typedef struct _ISAPNP_COMPATIBLE_ID_ENTRY LIST_ENTRY IdLink; } ISAPNP_COMPATIBLE_ID_ENTRY, *PISAPNP_COMPATIBLE_ID_ENTRY; -typedef struct _ISAPNP_ALTERNATIVES +typedef enum { - ISAPNP_IO_DESCRIPTION Io[ISAPNP_MAX_ALTERNATIVES]; - ISAPNP_IRQ_DESCRIPTION Irq[ISAPNP_MAX_ALTERNATIVES]; - ISAPNP_DMA_DESCRIPTION Dma[ISAPNP_MAX_ALTERNATIVES]; - ISAPNP_MEMRANGE_DESCRIPTION MemRange[ISAPNP_MAX_ALTERNATIVES]; - ISAPNP_MEMRANGE32_DESCRIPTION MemRange32[ISAPNP_MAX_ALTERNATIVES]; - UCHAR Priority[ISAPNP_MAX_ALTERNATIVES]; - UCHAR IoIndex; - UCHAR IrqIndex; - UCHAR DmaIndex; - UCHAR MemRangeIndex; - UCHAR MemRange32Index; + dfNotStarted, + dfStarted, + dfDone +} ISAPNP_DEPENDENT_FUNCTION_STATE; - _Field_range_(0, ISAPNP_MAX_ALTERNATIVES) - UCHAR Count; -} ISAPNP_ALTERNATIVES, *PISAPNP_ALTERNATIVES; +typedef struct _ISAPNP_RESOURCE +{ + UCHAR Type; +#define ISAPNP_RESOURCE_TYPE_END 0 +#define ISAPNP_RESOURCE_TYPE_IO 1 +#define ISAPNP_RESOURCE_TYPE_IRQ 2 +#define ISAPNP_RESOURCE_TYPE_DMA 3 +#define ISAPNP_RESOURCE_TYPE_MEMRANGE 4 +#define ISAPNP_RESOURCE_TYPE_MEMRANGE32 5 +#define ISAPNP_RESOURCE_TYPE_START_DEPENDENT 6 +#define ISAPNP_RESOURCE_TYPE_END_DEPENDENT 7 + + union + { + ISAPNP_IO_DESCRIPTION IoDescription; + ISAPNP_IRQ_DESCRIPTION IrqDescription; + ISAPNP_DMA_DESCRIPTION DmaDescription; + ISAPNP_MEMRANGE_DESCRIPTION MemRangeDescription; + ISAPNP_MEMRANGE32_DESCRIPTION MemRange32Description; + UCHAR Priority; + }; +} ISAPNP_RESOURCE, *PISAPNP_RESOURCE; typedef struct _ISAPNP_LOGICAL_DEVICE { @@ -92,6 +101,12 @@ typedef struct _ISAPNP_LOGICAL_DEVICE /** Cleared when the device has no boot resources */ #define ISAPNP_HAS_RESOURCES 0x00000004 +/** The card implements 24-bit memory decoder */ +#define ISAPNP_HAS_MEM24_DECODER 0x00000008 + +/** The card implements 32-bit memory decoder */ +#define ISAPNP_HAS_MEM32_DECODER 0x00000010 + /** * @name The card data. * @{ @@ -109,7 +124,7 @@ typedef struct _ISAPNP_LOGICAL_DEVICE UCHAR LDN; UCHAR LogVendorId[3]; USHORT LogProdId; - PISAPNP_ALTERNATIVES Alternatives; + PISAPNP_RESOURCE Resources; PSTR FriendlyName; LIST_ENTRY CompatibleIdList; @@ -120,43 +135,3 @@ typedef struct _ISAPNP_LOGICAL_DEVICE ISAPNP_MEMRANGE32 MemRange32[4]; /**@}*/ } ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE; - -FORCEINLINE -BOOLEAN -HasIoAlternatives( - _In_ PISAPNP_ALTERNATIVES Alternatives) -{ - return (Alternatives->Io[0].Length != 0); -} - -FORCEINLINE -BOOLEAN -HasIrqAlternatives( - _In_ PISAPNP_ALTERNATIVES Alternatives) -{ - return (Alternatives->Irq[0].Mask != 0); -} - -FORCEINLINE -BOOLEAN -HasDmaAlternatives( - _In_ PISAPNP_ALTERNATIVES Alternatives) -{ - return (Alternatives->Dma[0].Mask != 0); -} - -FORCEINLINE -BOOLEAN -HasMemoryAlternatives( - _In_ PISAPNP_ALTERNATIVES Alternatives) -{ - return (Alternatives->MemRange[0].Length != 0); -} - -FORCEINLINE -BOOLEAN -HasMemory32Alternatives( - _In_ PISAPNP_ALTERNATIVES Alternatives) -{ - return (Alternatives->MemRange32[0].Length != 0); -} diff --git a/drivers/bus/isapnp/pdo.c b/drivers/bus/isapnp/pdo.c index 5e8979ad274..26d4cfc8a94 100644 --- a/drivers/bus/isapnp/pdo.c +++ b/drivers/bus/isapnp/pdo.c @@ -488,12 +488,6 @@ IsaPdoQueryResources( return STATUS_SUCCESS; } - if (!(PdoExt->IsaPnpDevice->Flags & ISAPNP_HAS_RESOURCES)) - { - Irp->IoStatus.Information = 0; - return STATUS_SUCCESS; - } - if (!PdoExt->ResourceList) return Irp->IoStatus.Status; @@ -847,8 +841,8 @@ IsaPnpRemoveLogicalDeviceDO( if (LogDev->FriendlyName) ExFreePoolWithTag(LogDev->FriendlyName, TAG_ISAPNP); - if (LogDev->Alternatives) - ExFreePoolWithTag(LogDev->Alternatives, TAG_ISAPNP); + if (LogDev->Resources) + ExFreePoolWithTag(LogDev->Resources, TAG_ISAPNP); Entry = LogDev->CompatibleIdList.Flink; while (Entry != &LogDev->CompatibleIdList) @@ -983,18 +977,16 @@ IsaPdoPnp( break; case IRP_MN_SURPRISE_REMOVAL: - if (PdoExt->Common.Signature == IsaPnpLogicalDevice) - Status = IsaPdoRemoveDevice(PdoExt, FALSE); - else - Status = IsaReadPortRemoveDevice(PdoExt, FALSE); - break; - case IRP_MN_REMOVE_DEVICE: + { + BOOLEAN FinalRemove = (IrpSp->MinorFunction == IRP_MN_REMOVE_DEVICE); + if (PdoExt->Common.Signature == IsaPnpLogicalDevice) - Status = IsaPdoRemoveDevice(PdoExt, TRUE); + Status = IsaPdoRemoveDevice(PdoExt, FinalRemove); else - Status = IsaReadPortRemoveDevice(PdoExt, TRUE); + Status = IsaReadPortRemoveDevice(PdoExt, FinalRemove); break; + } case IRP_MN_QUERY_PNP_DEVICE_STATE: Status = IsaPdoQueryPnpDeviceState(PdoExt, Irp);