https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ca42de9c314c5c97e212dc...
commit ca42de9c314c5c97e212dc08e6a2e2df15324151 Author: Dmitry Borisov di.sean@protonmail.com AuthorDate: Sat Mar 20 20:50:34 2021 +0600 Commit: Dmitry Borisov di.sean@protonmail.com CommitDate: Sun Jun 20 19:24:31 2021 +0600
[ISAPNP] Rewrite the tag parser
- Support all resource descriptors. - Optimize card identification. - Detect cards that is no longer present on the bus. - Deactivate cards after the identification phase; they will be activated by start device IRP. - Provide a device description and compatible IDs to the device manager. - Prevent duplicate IDs across multiple logical devices. - Suppress warning about the usage of literals in port addresses. --- drivers/bus/isapnp/hardware.c | 868 +++++++++++++++++++++++++++++++++++++----- drivers/bus/isapnp/isapnp.c | 8 +- drivers/bus/isapnp/isapnp.h | 120 +++++- drivers/bus/isapnp/isapnphw.h | 72 ++-- drivers/bus/isapnp/pdo.c | 194 +++++++++- 5 files changed, 1114 insertions(+), 148 deletions(-)
diff --git a/drivers/bus/isapnp/hardware.c b/drivers/bus/isapnp/hardware.c index 6673e200194..9dae1c66eb6 100644 --- a/drivers/bus/isapnp/hardware.c +++ b/drivers/bus/isapnp/hardware.c @@ -4,6 +4,7 @@ * PURPOSE: Hardware support code * COPYRIGHT: Copyright 2010 Cameron Gutman cameron.gutman@reactos.org * Copyright 2020 Hervé Poussineau hpoussin@reactos.org + * Copyright 2021 Dmitry Borisov di.sean@protonmail.com */
#include "isapnp.h" @@ -11,6 +12,17 @@ #define NDEBUG #include <debug.h>
+#ifdef _MSC_VER +#pragma warning(disable:28138) /* ISA bus always uses hardcoded port addresses */ +#endif + +typedef enum +{ + dfNotStarted, + dfStarted, + dfDone +} DEPEDENT_FUNCTION_STATE; + static inline VOID @@ -291,6 +303,24 @@ 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 @@ -318,24 +348,48 @@ IsaPnpChecksum(
static CODE_SEG("PAGE") -BOOLEAN +VOID +IsaPnpExtractAscii( + _Out_writes_all_(3) PUCHAR Buffer, + _In_ USHORT CompressedData) +{ + PAGED_CODE(); + + Buffer[0] = ((CompressedData >> 2) & 0x1F) + 'A' - 1; + Buffer[1] = (((CompressedData & 0x3) << 3) | ((CompressedData >> 13) & 0x7)) + 'A' - 1; + Buffer[2] = ((CompressedData >> 8) & 0x1F) + 'A' - 1; +} + +static +CODE_SEG("PAGE") +NTSTATUS ReadTags( _In_ PUCHAR ReadDataPort, - _In_ USHORT LogDev, - _Inout_ PISAPNP_LOGICAL_DEVICE LogDevice) + _Out_writes_(ISAPNP_MAX_RESOURCEDATA) PUCHAR Buffer, + _In_ ULONG MaxLength, + _Out_ PUSHORT MaxLogDev) { - BOOLEAN res = FALSE; - PVOID Buffer; - USHORT Tag, TagLen, MaxLen; - ULONG NumberOfIo = 0, NumberOfIrq = 0, NumberOfDma = 0; - PAGED_CODE();
- LogDev += 1; + *MaxLogDev = 0;
while (TRUE) { + UCHAR Tag; + USHORT TagLen; + + if (MaxLength < 1) + return STATUS_BUFFER_OVERFLOW; + Tag = PeekByte(ReadDataPort); + if (Tag == 0) + { + DPRINT("Invalid tag\n"); + return STATUS_INVALID_PARAMETER_1; + } + *Buffer++ = Tag; + --MaxLength; + if (ISAPNP_IS_SMALL_TAG(Tag)) { TagLen = ISAPNP_SMALL_TAG_LEN(Tag); @@ -343,64 +397,623 @@ ReadTags( } else { - TagLen = PeekByte(ReadDataPort) + (PeekByte(ReadDataPort) << 8); + UCHAR Temp[2]; + + if (MaxLength < sizeof(Temp)) + return STATUS_BUFFER_OVERFLOW; + + Peek(ReadDataPort, &Temp, sizeof(Temp)); + *Buffer++ = Temp[0]; + *Buffer++ = Temp[1]; + MaxLength -= sizeof(Temp); + + TagLen = Temp[0] + (Temp[1] << 8); Tag = ISAPNP_LARGE_TAG_NAME(Tag); } - if (Tag == ISAPNP_TAG_END) - break;
- Buffer = NULL; - if (Tag == ISAPNP_TAG_LOGDEVID) - { - MaxLen = sizeof(LogDevice->LogDevId); - Buffer = &LogDevice->LogDevId; - LogDev--; - } - else if (Tag == ISAPNP_TAG_IRQ && NumberOfIrq < ARRAYSIZE(LogDevice->Irq)) - { - MaxLen = sizeof(LogDevice->Irq[NumberOfIrq].Description); - Buffer = &LogDevice->Irq[NumberOfIrq].Description; - NumberOfIrq++; - } - else if (Tag == ISAPNP_TAG_IOPORT && NumberOfIo < ARRAYSIZE(LogDevice->Io)) + if (Tag == 0xFF && TagLen == 0xFFFF) { - MaxLen = sizeof(LogDevice->Io[NumberOfIo].Description); - Buffer = &LogDevice->Io[NumberOfIo].Description; - NumberOfIo++; + DPRINT("Invalid tag\n"); + return STATUS_INVALID_PARAMETER_2; } - else if (Tag == ISAPNP_TAG_DMA && NumberOfDma < ARRAYSIZE(LogDevice->Dma)) + + if (TagLen > MaxLength) + return STATUS_BUFFER_OVERFLOW; + + Peek(ReadDataPort, Buffer, TagLen); + MaxLength -= TagLen; + Buffer += TagLen; + + if (Tag == ISAPNP_TAG_LOGDEVID) + (*MaxLogDev)++; + + if (Tag == ISAPNP_TAG_END) + break; + } + + return STATUS_SUCCESS; +} + +static +CODE_SEG("PAGE") +VOID +FreeLogicalDevice( + _In_ __drv_freesMem(Mem) PISAPNP_LOGICAL_DEVICE LogDevice) +{ + PLIST_ENTRY Entry; + + PAGED_CODE(); + + if (LogDevice->FriendlyName) + ExFreePoolWithTag(LogDevice->FriendlyName, TAG_ISAPNP); + + if (LogDevice->Alternatives) + ExFreePoolWithTag(LogDevice->Alternatives, TAG_ISAPNP); + + Entry = LogDevice->CompatibleIdList.Flink; + while (Entry != &LogDevice->CompatibleIdList) + { + PISAPNP_COMPATIBLE_ID_ENTRY CompatibleId = + CONTAINING_RECORD(Entry, ISAPNP_COMPATIBLE_ID_ENTRY, IdLink); + + RemoveEntryList(&CompatibleId->IdLink); + + Entry = Entry->Flink; + + ExFreePoolWithTag(CompatibleId, TAG_ISAPNP); + } + + ExFreePoolWithTag(LogDevice, TAG_ISAPNP); +} + +static +CODE_SEG("PAGE") +NTSTATUS +ParseTags( + _In_ PUCHAR ResourceData, + _In_ USHORT LogDevToParse, + _Inout_ PISAPNP_LOGICAL_DEVICE LogDevice) +{ + USHORT LogDev; + DEPEDENT_FUNCTION_STATE DfState = dfNotStarted; + PUCHAR IdStrPos = NULL; + USHORT IdStrLen = 0; + UCHAR NumberOfIo = 0, + NumberOfIrq = 0, + NumberOfDma = 0, + NumberOfMemRange = 0, + NumberOfMemRange32 = 0, + NumberOfDepedentSet = 0; + + PAGED_CODE(); + + DPRINT("%s for CSN %u, LDN %u\n", __FUNCTION__, LogDevice->CSN, LogDevice->LDN); + + LogDev = LogDevToParse + 1; + + while (TRUE) + { + UCHAR Tag; + USHORT TagLen; + + Tag = *ResourceData++; + + if (ISAPNP_IS_SMALL_TAG(Tag)) { - MaxLen = sizeof(LogDevice->Dma[NumberOfDma].Description); - Buffer = &LogDevice->Dma[NumberOfDma].Description; - NumberOfDma++; + TagLen = ISAPNP_SMALL_TAG_LEN(Tag); + Tag = ISAPNP_SMALL_TAG_NAME(Tag); } - else if (LogDev == 0) + else { - DPRINT1("Found unknown tag 0x%x (len %d)\n", Tag, TagLen); + TagLen = *ResourceData++; + TagLen += *ResourceData++ << 8; + + Tag = ISAPNP_LARGE_TAG_NAME(Tag); }
- if (Buffer && LogDev == 0) + switch (Tag) { - res = TRUE; - if (MaxLen > TagLen) + case ISAPNP_TAG_LOGDEVID: { - Peek(ReadDataPort, Buffer, TagLen); + ISAPNP_LOGDEVID Temp; + + --LogDev; + + if (LogDev != 0 || + (TagLen > sizeof(ISAPNP_LOGDEVID) || + TagLen < (sizeof(ISAPNP_LOGDEVID) - 1))) + { + goto SkipTag; + } + + PeekCached(ResourceData, &Temp, TagLen); + ResourceData += TagLen; + + DPRINT("Found tag 0x%X (len %u)\n" + " VendorId 0x%04X\n" + " ProdId 0x%04X\n", + Tag, TagLen, + Temp.VendorId, + Temp.ProdId); + + IsaPnpExtractAscii(LogDevice->LogVendorId, Temp.VendorId); + LogDevice->LogProdId = RtlUshortByteSwap(Temp.ProdId); + + break; } - else + + case ISAPNP_TAG_COMPATDEVID: { - Peek(ReadDataPort, Buffer, MaxLen); - Peek(ReadDataPort, NULL, TagLen - MaxLen); + ISAPNP_COMPATID Temp; + PISAPNP_COMPATIBLE_ID_ENTRY CompatibleId; + + if (LogDev != 0 || TagLen != sizeof(ISAPNP_COMPATID)) + goto SkipTag; + + CompatibleId = ExAllocatePoolWithTag(PagedPool, + sizeof(ISAPNP_COMPATIBLE_ID_ENTRY), + TAG_ISAPNP); + if (!CompatibleId) + return STATUS_INSUFFICIENT_RESOURCES; + + PeekCached(ResourceData, &Temp, TagLen); + ResourceData += TagLen; + + DPRINT("Found tag 0x%X (len %u)\n" + " VendorId 0x%04X\n" + " ProdId 0x%04X\n", + Tag, TagLen, + Temp.VendorId, + Temp.ProdId); + + IsaPnpExtractAscii(CompatibleId->VendorId, Temp.VendorId); + CompatibleId->ProdId = RtlUshortByteSwap(Temp.ProdId); + + InsertTailList(&LogDevice->CompatibleIdList, &CompatibleId->IdLink); + + break; } - } - else - { - /* We don't want to read informations on this - * logical device, or we don't know the tag. */ - Peek(ReadDataPort, NULL, TagLen); - } - };
- return res; + case ISAPNP_TAG_IRQ: + { + PISAPNP_IRQ_DESCRIPTION Description; + + if (LogDev != 0 || + (TagLen > sizeof(ISAPNP_IRQ_DESCRIPTION) || + TagLen < (sizeof(ISAPNP_IRQ_DESCRIPTION) - 1)) || + NumberOfIrq >= RTL_NUMBER_OF(LogDevice->Irq)) + { + goto SkipTag; + } + + if (DfState == dfStarted) + { + if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + goto SkipTag; + + Description = &LogDevice->Alternatives->Irq[NumberOfDepedentSet]; + } + else + { + Description = &LogDevice->Irq[NumberOfIrq].Description; + + LogDevice->Irq[NumberOfIrq].Index = NumberOfIrq; + ++NumberOfIrq; + } + + PeekCached(ResourceData, Description, TagLen); + ResourceData += TagLen; + + if (TagLen == (sizeof(ISAPNP_IRQ_DESCRIPTION) - 1)) + Description->Information = 0x01; + + DPRINT("Found tag 0x%X (len %u)\n" + " Mask 0x%X\n" + " Information 0x%X\n", + Tag, TagLen, + Description->Mask, + Description->Information); + + break; + } + + case ISAPNP_TAG_DMA: + { + PISAPNP_DMA_DESCRIPTION Description; + + if (LogDev != 0 || TagLen != sizeof(ISAPNP_DMA_DESCRIPTION) || + NumberOfDma >= RTL_NUMBER_OF(LogDevice->Dma)) + { + goto SkipTag; + } + + if (DfState == dfStarted) + { + if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + goto SkipTag; + + Description = &LogDevice->Alternatives->Dma[NumberOfDepedentSet]; + } + else + { + Description = &LogDevice->Dma[NumberOfDma].Description; + + LogDevice->Dma[NumberOfDma].Index = NumberOfDma; + ++NumberOfDma; + } + + PeekCached(ResourceData, Description, TagLen); + ResourceData += TagLen; + + DPRINT("Found tag 0x%X (len %u)\n" + " Mask 0x%X\n" + " Information 0x%X\n", + Tag, TagLen, + Description->Mask, + Description->Information); + + break; + } + + case ISAPNP_TAG_STARTDEP: + { + if (LogDev != 0 || TagLen > 1 || + NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + { + goto SkipTag; + } + + 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 + { + goto SkipTag; + } + + ++LogDevice->Alternatives->Count; + + if (TagLen != 1) + { + LogDevice->Alternatives->Priority[NumberOfDepedentSet] = 1; + } + else + { + PeekCached(ResourceData, + &LogDevice->Alternatives->Priority[NumberOfDepedentSet], + TagLen); + ResourceData += TagLen; + } + + DPRINT("*** Start depedent set %u, priority %u ***\n", + NumberOfDepedentSet, + LogDevice->Alternatives->Priority[NumberOfDepedentSet]); + + break; + } + + case ISAPNP_TAG_ENDDEP: + { + if (LogDev != 0 || DfState != dfStarted) + goto SkipTag; + + 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"); + + break; + } + + case ISAPNP_TAG_IOPORT: + { + PISAPNP_IO_DESCRIPTION Description; + + if (LogDev != 0 || TagLen != sizeof(ISAPNP_IO_DESCRIPTION) || + NumberOfIo >= RTL_NUMBER_OF(LogDevice->Io)) + { + goto SkipTag; + } + + if (DfState == dfStarted) + { + if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + goto SkipTag; + + Description = &LogDevice->Alternatives->Io[NumberOfDepedentSet]; + } + else + { + Description = &LogDevice->Io[NumberOfIo].Description; + + LogDevice->Io[NumberOfIo].Index = NumberOfIo; + ++NumberOfIo; + } + + PeekCached(ResourceData, Description, TagLen); + ResourceData += TagLen; + + DPRINT("Found tag 0x%X (len %u)\n" + " Information 0x%X\n" + " Minimum 0x%X\n" + " Maximum 0x%X\n" + " Alignment 0x%X\n" + " Length 0x%X\n", + Tag, TagLen, + Description->Information, + Description->Minimum, + Description->Maximum, + Description->Alignment, + Description->Length); + + break; + } + + case ISAPNP_TAG_FIXEDIO: + { + ISAPNP_FIXED_IO_DESCRIPTION Temp; + PISAPNP_IO_DESCRIPTION Description; + + if (LogDev != 0 || TagLen != sizeof(ISAPNP_FIXED_IO_DESCRIPTION) || + NumberOfIo >= RTL_NUMBER_OF(LogDevice->Io)) + { + goto SkipTag; + } + + if (DfState == dfStarted) + { + if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + goto SkipTag; + + Description = &LogDevice->Alternatives->Io[NumberOfDepedentSet]; + } + else + { + Description = &LogDevice->Io[NumberOfIo].Description; + + LogDevice->Io[NumberOfIo].Index = NumberOfIo; + ++NumberOfIo; + } + + PeekCached(ResourceData, &Temp, TagLen); + ResourceData += TagLen; + + Description->Information = 0; + Description->Minimum = + Description->Maximum = Temp.IoBase; + Description->Alignment = 1; + Description->Length = Temp.Length; + + DPRINT("Found tag 0x%X (len %u)\n" + " IoBase 0x%X\n" + " Length 0x%X\n", + Tag, TagLen, + Temp.IoBase, + Temp.Length); + + break; + } + + case ISAPNP_TAG_END: + { + if (IdStrPos) + { + PSTR End; + + LogDevice->FriendlyName = ExAllocatePoolWithTag(PagedPool, + IdStrLen + sizeof(ANSI_NULL), + TAG_ISAPNP); + if (!LogDevice->FriendlyName) + return STATUS_INSUFFICIENT_RESOURCES; + + PeekCached(IdStrPos, LogDevice->FriendlyName, IdStrLen); + + End = LogDevice->FriendlyName + IdStrLen - 1; + while (End > LogDevice->FriendlyName && *End == ' ') + { + --End; + } + *++End = ANSI_NULL; + } + + return STATUS_SUCCESS; + } + + case ISAPNP_TAG_MEMRANGE: + { + PISAPNP_MEMRANGE_DESCRIPTION Description; + + if (LogDev != 0 || TagLen != sizeof(ISAPNP_MEMRANGE_DESCRIPTION) || + NumberOfMemRange >= RTL_NUMBER_OF(LogDevice->MemRange)) + { + goto SkipTag; + } + + if (DfState == dfStarted) + { + if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + goto SkipTag; + + Description = &LogDevice->Alternatives->MemRange[NumberOfDepedentSet]; + } + else + { + Description = &LogDevice->MemRange[NumberOfMemRange].Description; + + LogDevice->MemRange[NumberOfMemRange].Index = NumberOfMemRange; + ++NumberOfMemRange; + } + + PeekCached(ResourceData, Description, TagLen); + ResourceData += TagLen; + + DPRINT("Found tag 0x%X (len %u)\n" + " Information 0x%X\n" + " Minimum 0x%X\n" + " Maximum 0x%X\n" + " Alignment 0x%X\n" + " Length 0x%X\n", + Tag, TagLen, + Description->Information, + Description->Minimum, + Description->Maximum, + Description->Alignment, + Description->Length); + + break; + } + + case ISAPNP_TAG_ANSISTR: + { + /* If logical device identifier is not supplied, use card identifier */ + if (LogDev == LogDevToParse + 1 || LogDev == 0) + { + IdStrPos = ResourceData; + IdStrLen = TagLen; + + ResourceData += TagLen; + + DPRINT("Found tag 0x%X (len %u)\n" + " '%.*s'\n", + Tag, TagLen, + IdStrLen, + IdStrPos); + } + else + { + goto SkipTag; + } + + break; + } + + case ISAPNP_TAG_MEM32RANGE: + { + PISAPNP_MEMRANGE32_DESCRIPTION Description; + + if (LogDev != 0 || TagLen != sizeof(ISAPNP_MEMRANGE32_DESCRIPTION) || + NumberOfMemRange32 >= RTL_NUMBER_OF(LogDevice->MemRange32)) + { + goto SkipTag; + } + + if (DfState == dfStarted) + { + if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + goto SkipTag; + + Description = &LogDevice->Alternatives->MemRange32[NumberOfDepedentSet]; + } + else + { + Description = &LogDevice->MemRange32[NumberOfMemRange32].Description; + + LogDevice->MemRange32[NumberOfMemRange32].Index = NumberOfMemRange32; + ++NumberOfMemRange32; + } + + PeekCached(ResourceData, Description, TagLen); + ResourceData += TagLen; + + DPRINT("Found tag 0x%X (len %u)\n" + " Information 0x%X\n" + " Minimum 0x%08lX\n" + " Maximum 0x%08lX\n" + " Alignment 0x%08lX\n" + " Length 0x%08lX\n", + Tag, TagLen, + Description->Information, + Description->Minimum, + Description->Maximum, + Description->Alignment, + Description->Length); + + break; + } + + case ISAPNP_TAG_FIXEDMEM32RANGE: + { + ISAPNP_FIXEDMEMRANGE_DESCRIPTION Temp; + PISAPNP_MEMRANGE32_DESCRIPTION Description; + + if (LogDev != 0 || TagLen != sizeof(ISAPNP_FIXEDMEMRANGE_DESCRIPTION) || + NumberOfMemRange32 >= RTL_NUMBER_OF(LogDevice->MemRange32)) + { + goto SkipTag; + } + + if (DfState == dfStarted) + { + if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) + goto SkipTag; + + Description = &LogDevice->Alternatives->MemRange32[NumberOfDepedentSet]; + } + else + { + Description = &LogDevice->MemRange32[NumberOfMemRange32].Description; + + LogDevice->MemRange32[NumberOfMemRange32].Index = NumberOfMemRange32; + ++NumberOfMemRange32; + } + + PeekCached(ResourceData, &Temp, TagLen); + ResourceData += TagLen; + + Description->Information = Temp.Information; + Description->Minimum = + Description->Maximum = Temp.MemoryBase; + Description->Alignment = 1; + Description->Length = Temp.Length; + + DPRINT("Found tag 0x%X (len %u)\n" + " Information 0x%X\n" + " MemoryBase 0x%08lX\n" + " Length 0x%08lX\n", + Tag, TagLen, + Temp.Information, + Temp.MemoryBase, + Temp.Length); + + break; + } + +SkipTag: + default: + { + if (LogDev == 0) + DPRINT("Found unknown tag 0x%X (len %u)\n", Tag, TagLen); + + /* We don't want to read informations on this + * logical device, or we don't know the tag. */ + ResourceData += TagLen; + break; + } + } + } }
static @@ -532,54 +1145,127 @@ DeviceActivation( WaitForKey(); }
-static +_Requires_lock_held_(FdoExt->DeviceSyncEvent) CODE_SEG("PAGE") NTSTATUS -ProbeIsaPnpBus( +IsaHwFillDeviceList( _In_ PISAPNP_FDO_EXTENSION FdoExt) { PISAPNP_LOGICAL_DEVICE LogDevice; - ISAPNP_IDENTIFIER Identifier; - USHORT Csn; - USHORT LogDev; + UCHAR Csn; ULONG i; + PLIST_ENTRY Entry; + PUCHAR ResourceData;
PAGED_CODE(); ASSERT(FdoExt->ReadDataPort);
- for (Csn = 1; Csn <= 0xFF; Csn++) + DPRINT("%s for read port 0x%p\n", __FUNCTION__, FdoExt->ReadDataPort); + + ResourceData = ExAllocatePoolWithTag(PagedPool, ISAPNP_MAX_RESOURCEDATA, TAG_ISAPNP); + if (!ResourceData) + { + DPRINT1("Failed to allocate memory for cache data\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + for (Entry = FdoExt->DeviceListHead.Flink; + Entry != &FdoExt->DeviceListHead; + Entry = Entry->Flink) + { + LogDevice = CONTAINING_RECORD(Entry, ISAPNP_LOGICAL_DEVICE, DeviceLink); + + LogDevice->Flags &= ~ISAPNP_PRESENT; + } + + WaitForKey(); + SendKey(); + + for (Csn = 1; Csn <= FdoExt->Cards; Csn++) { - for (LogDev = 0; LogDev <= 0xFF; LogDev++) + NTSTATUS Status; + UCHAR TempId[3], LogDev; + ISAPNP_IDENTIFIER Identifier; + USHORT MaxLogDev; + + Wake(Csn); + + Peek(FdoExt->ReadDataPort, &Identifier, sizeof(Identifier)); + + IsaPnpExtractAscii(TempId, Identifier.VendorId); + Identifier.ProdId = RtlUshortByteSwap(Identifier.ProdId); + + Status = ReadTags(FdoExt->ReadDataPort, ResourceData, ISAPNP_MAX_RESOURCEDATA, &MaxLogDev); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to read tags with status 0x%08lx, CSN %u\n", Status, Csn); + continue; + } + + DPRINT("Detected ISA PnP device - VID: '%.3s' PID: 0x%04x SN: 0x%08lX\n", + TempId, Identifier.ProdId, Identifier.Serial); + + for (LogDev = 0; LogDev < MaxLogDev; LogDev++) { + BOOLEAN IsAlreadyEnumerated = FALSE; + + for (Entry = FdoExt->DeviceListHead.Flink; + Entry != &FdoExt->DeviceListHead; + Entry = Entry->Flink) + { + LogDevice = CONTAINING_RECORD(Entry, ISAPNP_LOGICAL_DEVICE, DeviceLink); + + /* This logical device has already been enumerated */ + if ((LogDevice->SerialNumber == Identifier.Serial) && + (RtlCompareMemory(LogDevice->VendorId, TempId, 3) == 3) && + (LogDevice->ProdId == Identifier.ProdId) && + (LogDevice->LDN == LogDev)) + { + LogDevice->Flags |= ISAPNP_PRESENT; + + /* Assign a new CSN */ + LogDevice->CSN = Csn; + + if (LogDevice->Pdo) + { + PISAPNP_PDO_EXTENSION PdoExt = LogDevice->Pdo->DeviceExtension; + + if (PdoExt->Common.State == dsStarted) + ActivateDevice(LogDev); + } + + DPRINT("Skip CSN %u, LDN %u\n", LogDevice->CSN, LogDevice->LDN); + IsAlreadyEnumerated = TRUE; + break; + } + } + + if (IsAlreadyEnumerated) + continue; + LogDevice = ExAllocatePoolZero(NonPagedPool, sizeof(ISAPNP_LOGICAL_DEVICE), TAG_ISAPNP); if (!LogDevice) - return STATUS_NO_MEMORY; + { + DPRINT1("Failed to allocate logical device!\n"); + goto Deactivate; + } + + InitializeListHead(&LogDevice->CompatibleIdList);
LogDevice->CSN = Csn; LogDevice->LDN = LogDev;
- WaitForKey(); - SendKey(); - Wake(Csn); - - Peek(FdoExt->ReadDataPort, &Identifier, sizeof(Identifier)); - - if (Identifier.VendorId & 0x80) + Status = ParseTags(ResourceData, LogDev, LogDevice); + if (!NT_SUCCESS(Status)) { - ExFreePoolWithTag(LogDevice, TAG_ISAPNP); - return STATUS_SUCCESS; + DPRINT1("Failed to parse tags with status 0x%08lx, CSN %u, LDN %u\n", + Status, LogDevice->CSN, LogDevice->LDN); + FreeLogicalDevice(LogDevice); + goto Deactivate; }
- if (!ReadTags(FdoExt->ReadDataPort, LogDev, LogDevice)) - break; - WriteLogicalDeviceNumber(LogDev);
- LogDevice->VendorId[0] = ((LogDevice->LogDevId.VendorId >> 2) & 0x1f) + 'A' - 1, - LogDevice->VendorId[1] = (((LogDevice->LogDevId.VendorId & 0x3) << 3) | ((LogDevice->LogDevId.VendorId >> 13) & 0x7)) + 'A' - 1, - LogDevice->VendorId[2] = ((LogDevice->LogDevId.VendorId >> 8) & 0x1f) + 'A' - 1, - LogDevice->ProdId = RtlUshortByteSwap(LogDevice->LogDevId.ProdId); - LogDevice->SerialNumber = Identifier.Serial; for (i = 0; i < ARRAYSIZE(LogDevice->Io); i++) LogDevice->Io[i].CurrentBase = ReadIoBase(FdoExt->ReadDataPort, i); for (i = 0; i < ARRAYSIZE(LogDevice->Irq); i++) @@ -592,27 +1278,37 @@ ProbeIsaPnpBus( LogDevice->Dma[i].CurrentChannel = ReadDmaChannel(FdoExt->ReadDataPort, i); }
- DPRINT1("Detected ISA PnP device - VID: '%3s' PID: 0x%x SN: 0x%08x IoBase: 0x%x IRQ:0x%x\n", - LogDevice->VendorId, LogDevice->ProdId, LogDevice->SerialNumber, LogDevice->Io[0].CurrentBase, LogDevice->Irq[0].CurrentNo); + IsaPnpExtractAscii(LogDevice->VendorId, Identifier.VendorId); + LogDevice->ProdId = Identifier.ProdId; + LogDevice->SerialNumber = Identifier.Serial;
- WaitForKey(); + if (MaxLogDev > 1) + LogDevice->Flags |= ISAPNP_HAS_MULTIPLE_LOGDEVS; + + LogDevice->Flags |= ISAPNP_PRESENT;
InsertTailList(&FdoExt->DeviceListHead, &LogDevice->DeviceLink); FdoExt->DeviceCount++; + + /* Now we wait for the start device IRP */ +Deactivate: + DeactivateDevice(LogDev); } }
+ ExFreePoolWithTag(ResourceData, TAG_ISAPNP); + return STATUS_SUCCESS; }
CODE_SEG("PAGE") -NTSTATUS +ULONG IsaHwTryReadDataPort( _In_ PUCHAR ReadDataPort) { PAGED_CODE();
- return TryIsolate(ReadDataPort) > 0 ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; + return TryIsolate(ReadDataPort); }
_IRQL_requires_max_(DISPATCH_LEVEL) @@ -636,13 +1332,3 @@ IsaHwDeactivateDevice(
return STATUS_SUCCESS; } - -CODE_SEG("PAGE") -NTSTATUS -IsaHwFillDeviceList( - _In_ PISAPNP_FDO_EXTENSION FdoExt) -{ - PAGED_CODE(); - - return ProbeIsaPnpBus(FdoExt); -} diff --git a/drivers/bus/isapnp/isapnp.c b/drivers/bus/isapnp/isapnp.c index 41f52c9aed6..842929ee0ce 100644 --- a/drivers/bus/isapnp/isapnp.c +++ b/drivers/bus/isapnp/isapnp.c @@ -676,11 +676,11 @@ IsaPnpFillDeviceRelations( DPRINT("Rescan ISA PnP bus\n");
/* Run the isolation protocol */ - if (NT_SUCCESS(IsaHwTryReadDataPort(FdoExt->ReadDataPort))) - { - /* Card identification */ + FdoExt->Cards = IsaHwTryReadDataPort(FdoExt->ReadDataPort); + + /* Card identification */ + if (FdoExt->Cards > 0) (VOID)IsaHwFillDeviceList(FdoExt); - } }
ReadPortExt->Flags &= ~ISAPNP_SCANNED_BY_READ_PORT; diff --git a/drivers/bus/isapnp/isapnp.h b/drivers/bus/isapnp/isapnp.h index ed4a6027a9b..d80d05dced1 100644 --- a/drivers/bus/isapnp/isapnp.h +++ b/drivers/bus/isapnp/isapnp.h @@ -23,6 +23,12 @@ extern "C" {
#define TAG_ISAPNP 'pasI'
+/** @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 + typedef enum { dsStopped, @@ -33,6 +39,7 @@ typedef struct _ISAPNP_IO { USHORT CurrentBase; ISAPNP_IO_DESCRIPTION Description; + UCHAR Index; } ISAPNP_IO, *PISAPNP_IO;
typedef struct _ISAPNP_IRQ @@ -40,29 +47,92 @@ typedef struct _ISAPNP_IRQ UCHAR CurrentNo; UCHAR CurrentType; ISAPNP_IRQ_DESCRIPTION Description; + UCHAR Index; } ISAPNP_IRQ, *PISAPNP_IRQ;
typedef struct _ISAPNP_DMA { UCHAR CurrentChannel; ISAPNP_DMA_DESCRIPTION Description; + UCHAR Index; } ISAPNP_DMA, *PISAPNP_DMA;
+typedef struct _ISAPNP_MEMRANGE +{ + ULONG CurrentBase; + ULONG CurrentLength; + ISAPNP_MEMRANGE_DESCRIPTION Description; + UCHAR Index; +} ISAPNP_MEMRANGE, *PISAPNP_MEMRANGE; + +typedef struct _ISAPNP_MEMRANGE32 +{ + ULONG CurrentBase; + ULONG CurrentLength; + ISAPNP_MEMRANGE32_DESCRIPTION Description; + UCHAR Index; +} ISAPNP_MEMRANGE32, *PISAPNP_MEMRANGE32; + +typedef struct _ISAPNP_COMPATIBLE_ID_ENTRY +{ + UCHAR VendorId[3]; + USHORT ProdId; + LIST_ENTRY IdLink; +} ISAPNP_COMPATIBLE_ID_ENTRY, *PISAPNP_COMPATIBLE_ID_ENTRY; + +typedef struct _ISAPNP_ALTERNATIVES +{ + 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; + + _Field_range_(0, ISAPNP_MAX_ALTERNATIVES) + UCHAR Count; +} ISAPNP_ALTERNATIVES, *PISAPNP_ALTERNATIVES; + typedef struct _ISAPNP_LOGICAL_DEVICE { PDEVICE_OBJECT Pdo; - ISAPNP_LOGDEVID LogDevId; + + /** + * @name The card data. + * @{ + */ + UCHAR CSN; UCHAR VendorId[3]; USHORT ProdId; ULONG SerialNumber; + /**@}*/ + + /** + * @name The logical device data. + * @{ + */ + UCHAR LDN; + UCHAR LogVendorId[3]; + USHORT LogProdId; + LIST_ENTRY CompatibleIdList; + PSTR FriendlyName; + PISAPNP_ALTERNATIVES Alternatives; + ISAPNP_IO Io[8]; ISAPNP_IRQ Irq[2]; ISAPNP_DMA Dma[2]; - UCHAR CSN; - UCHAR LDN; + ISAPNP_MEMRANGE MemRange[4]; + ISAPNP_MEMRANGE32 MemRange32[4]; + /**@}*/
ULONG Flags; #define ISAPNP_PRESENT 0x00000001 /**< @brief Cleared when the device is physically removed. */ +#define ISAPNP_HAS_MULTIPLE_LOGDEVS 0x00000002 /**< @brief Indicates if the parent card has multiple logical devices. */
LIST_ENTRY DeviceLink; } ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE; @@ -98,6 +168,7 @@ typedef struct _ISAPNP_FDO_EXTENSION
PDRIVER_OBJECT DriverObject; PUCHAR ReadDataPort; + ULONG Cards; LIST_ENTRY BusLink; } ISAPNP_FDO_EXTENSION, *PISAPNP_FDO_EXTENSION;
@@ -165,6 +236,46 @@ IsaPnpReleaseDeviceDataLock( KeSetEvent(&FdoExt->DeviceSyncEvent, IO_NO_INCREMENT, FALSE); }
+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); +} + /* isapnp.c */
CODE_SEG("PAGE") @@ -218,10 +329,11 @@ IsaPnpRemoveLogicalDeviceDO(
/* hardware.c */ CODE_SEG("PAGE") -NTSTATUS +ULONG IsaHwTryReadDataPort( _In_ PUCHAR ReadDataPort);
+_Requires_lock_held_(FdoExt->DeviceSyncEvent) CODE_SEG("PAGE") NTSTATUS IsaHwFillDeviceList( diff --git a/drivers/bus/isapnp/isapnphw.h b/drivers/bus/isapnp/isapnphw.h index cc33c320683..b3d8021a62c 100644 --- a/drivers/bus/isapnp/isapnphw.h +++ b/drivers/bus/isapnp/isapnphw.h @@ -4,6 +4,7 @@ * PURPOSE: Hardware definitions * COPYRIGHT: Copyright 2010 Cameron Gutman cameron.gutman@reactos.org * Copyright 2020 Hervé Poussineau hpoussin@reactos.org + * Copyright 2021 Dmitry Borisov di.sean@protonmail.com */
#pragma once @@ -15,14 +16,6 @@ extern "C" { #define ISAPNP_ADDRESS 0x279 #define ISAPNP_WRITE_DATA 0xA79
-#define ISAPNP_READ_PORT_MIN 0x203 -#define ISAPNP_READ_PORT_START 0x213 -#define ISAPNP_READ_PORT_MAX 0x3FF -#define ISAPNP_READ_PORT_STEP 0x10 - -#define ISAPNP_CSN_MIN 0x01 -#define ISAPNP_CSN_MAX 0x0F - #define ISAPNP_READPORT 0x00 #define ISAPNP_SERIALISOLATION 0x01 #define ISAPNP_CONFIGCONTROL 0x02 @@ -58,11 +51,6 @@ extern "C" { #define ISAPNP_TAG_ENDDEP 0x07 #define ISAPNP_TAG_IOPORT 0x08 #define ISAPNP_TAG_FIXEDIO 0x09 -#define ISAPNP_TAG_RSVDSHORTA 0x0A -#define ISAPNP_TAG_RSVDSHORTB 0x0B -#define ISAPNP_TAG_RSVDSHORTC 0x0C -#define ISAPNP_TAG_RSVDSHORTD 0x0D -#define ISAPNP_TAG_VENDORSHORT 0x0E #define ISAPNP_TAG_END 0x0F
#define ISAPNP_IS_LARGE_TAG(t) (((t) & 0x80)) @@ -70,26 +58,10 @@ extern "C" { #define ISAPNP_TAG_MEMRANGE 0x81 #define ISAPNP_TAG_ANSISTR 0x82 #define ISAPNP_TAG_UNICODESTR 0x83 -#define ISAPNP_TAG_VENDORLONG 0x84 #define ISAPNP_TAG_MEM32RANGE 0x85 #define ISAPNP_TAG_FIXEDMEM32RANGE 0x86 -#define ISAPNP_TAG_RSVDLONG0 0xF0 -#define ISAPNP_TAG_RSVDLONG1 0xF1 -#define ISAPNP_TAG_RSVDLONG2 0xF2 -#define ISAPNP_TAG_RSVDLONG3 0xF3 -#define ISAPNP_TAG_RSVDLONG4 0xF4 -#define ISAPNP_TAG_RSVDLONG5 0xF5 -#define ISAPNP_TAG_RSVDLONG6 0xF6 -#define ISAPNP_TAG_RSVDLONG7 0xF7 -#define ISAPNP_TAG_RSVDLONG8 0xF8 -#define ISAPNP_TAG_RSVDLONG9 0xF9 -#define ISAPNP_TAG_RSVDLONGA 0xFA -#define ISAPNP_TAG_RSVDLONGB 0xFB -#define ISAPNP_TAG_RSVDLONGC 0xFC -#define ISAPNP_TAG_RSVDLONGD 0xFD -#define ISAPNP_TAG_RSVDLONGE 0xFE -#define ISAPNP_TAG_RSVDLONGF 0xFF -#define ISAPNP_TAG_PSEUDO_NEWBOARD 0x100 + +#include <pshpack1.h>
typedef struct _ISAPNP_IDENTIFIER { @@ -106,14 +78,11 @@ typedef struct _ISAPNP_LOGDEVID USHORT Flags; } ISAPNP_LOGDEVID, *PISAPNP_LOGDEVID;
-typedef struct _ISAPNP_DEVICEID +typedef struct _ISAPNP_COMPATID { - CHAR* Name; USHORT VendorId; USHORT ProdId; -} ISAPNP_DEVICEID, *PISAPNP_DEVICEID; - -#include <pshpack1.h> +} ISAPNP_COMPATID, *PISAPNP_COMPATID;
typedef struct _ISAPNP_IO_DESCRIPTION { @@ -124,6 +93,12 @@ typedef struct _ISAPNP_IO_DESCRIPTION UCHAR Length; } ISAPNP_IO_DESCRIPTION, *PISAPNP_IO_DESCRIPTION;
+typedef struct _ISAPNP_FIXED_IO_DESCRIPTION +{ + USHORT IoBase; + UCHAR Length; +} ISAPNP_FIXED_IO_DESCRIPTION, *PISAPNP_FIXED_IO_DESCRIPTION; + typedef struct _ISAPNP_IRQ_DESCRIPTION { USHORT Mask; @@ -136,6 +111,31 @@ typedef struct _ISAPNP_DMA_DESCRIPTION UCHAR Information; } ISAPNP_DMA_DESCRIPTION, *PISAPNP_DMA_DESCRIPTION;
+typedef struct _ISAPNP_MEMRANGE_DESCRIPTION +{ + UCHAR Information; + USHORT Minimum; + USHORT Maximum; + USHORT Alignment; + USHORT Length; +} ISAPNP_MEMRANGE_DESCRIPTION, *PISAPNP_MEMRANGE_DESCRIPTION; + +typedef struct _ISAPNP_MEMRANGE32_DESCRIPTION +{ + UCHAR Information; + ULONG Minimum; + ULONG Maximum; + ULONG Alignment; + ULONG Length; +} ISAPNP_MEMRANGE32_DESCRIPTION, *PISAPNP_MEMRANGE32_DESCRIPTION; + +typedef struct _ISAPNP_FIXEDMEMRANGE_DESCRIPTION +{ + UCHAR Information; + ULONG MemoryBase; + ULONG Length; +} ISAPNP_FIXEDMEMRANGE_DESCRIPTION, *PISAPNP_FIXEDMEMRANGE_DESCRIPTION; + #include <poppack.h>
#ifdef __cplusplus diff --git a/drivers/bus/isapnp/pdo.c b/drivers/bus/isapnp/pdo.c index 6e3676a01cc..67a30891ac1 100644 --- a/drivers/bus/isapnp/pdo.c +++ b/drivers/bus/isapnp/pdo.c @@ -130,6 +130,11 @@ IsaPdoQueryId( { CharCount = sizeof("ISAPNP\XXXFFFF");
+ if (LogDev->Flags & ISAPNP_HAS_MULTIPLE_LOGDEVS) + { + CharCount += sizeof("_DEV1234") - sizeof(ANSI_NULL); + } + Buffer = ExAllocatePoolWithTag(PagedPool, CharCount * sizeof(WCHAR), TAG_ISAPNP); @@ -147,6 +152,19 @@ IsaPdoQueryId( if (!NT_VERIFY(NT_SUCCESS(Status))) goto Failure;
+ if (LogDev->Flags & ISAPNP_HAS_MULTIPLE_LOGDEVS) + { + Status = RtlStringCchPrintfExW(End, + Remaining, + NULL, + NULL, + 0, + L"_DEV%04X", + LogDev->LDN); + if (!NT_VERIFY(NT_SUCCESS(Status))) + goto Failure; + } + DPRINT("Device ID: '%S'\n", Buffer); break; } @@ -157,6 +175,11 @@ IsaPdoQueryId( sizeof("*PNPxxxx") + sizeof(ANSI_NULL); /* multi-string */
+ if (LogDev->Flags & ISAPNP_HAS_MULTIPLE_LOGDEVS) + { + CharCount += sizeof("_DEV1234") - sizeof(ANSI_NULL); + } + Buffer = ExAllocatePoolWithTag(PagedPool, CharCount * sizeof(WCHAR), TAG_ISAPNP); @@ -177,6 +200,19 @@ IsaPdoQueryId( if (!NT_VERIFY(NT_SUCCESS(Status))) goto Failure;
+ if (LogDev->Flags & ISAPNP_HAS_MULTIPLE_LOGDEVS) + { + Status = RtlStringCchPrintfExW(End, + Remaining, + &End, + &Remaining, + 0, + L"_DEV%04X", + LogDev->LDN); + if (!NT_VERIFY(NT_SUCCESS(Status))) + goto Failure; + } + DPRINT(" '%S'\n", Buffer);
++End; @@ -190,8 +226,8 @@ IsaPdoQueryId( &Remaining, 0, L"*%.3S%04x", - LogDev->VendorId, - LogDev->ProdId); + LogDev->LogVendorId, + LogDev->LogProdId); if (!NT_VERIFY(NT_SUCCESS(Status))) goto Failure;
@@ -204,7 +240,57 @@ IsaPdoQueryId( }
case BusQueryCompatibleIDs: - return STATUS_NOT_IMPLEMENTED; + { + PLIST_ENTRY Entry; + + for (Entry = LogDev->CompatibleIdList.Flink, CharCount = 0; + Entry != &LogDev->CompatibleIdList; + Entry = Entry->Flink) + { + CharCount += sizeof("*PNPxxxx"); + } + CharCount += sizeof(ANSI_NULL); /* multi-string */ + + if (CharCount == sizeof(ANSI_NULL)) + return Irp->IoStatus.Status; + + Buffer = ExAllocatePoolWithTag(PagedPool, + CharCount * sizeof(WCHAR), + TAG_ISAPNP); + if (!Buffer) + return STATUS_INSUFFICIENT_RESOURCES; + + DPRINT("Compatible IDs:\n"); + + for (Entry = LogDev->CompatibleIdList.Flink, End = Buffer, Remaining = CharCount; + Entry != &LogDev->CompatibleIdList; + Entry = Entry->Flink) + { + PISAPNP_COMPATIBLE_ID_ENTRY CompatibleId = + CONTAINING_RECORD(Entry, ISAPNP_COMPATIBLE_ID_ENTRY, IdLink); + + IdStart = End; + Status = RtlStringCchPrintfExW(End, + Remaining, + &End, + &Remaining, + 0, + L"*%.3S%04x", + CompatibleId->VendorId, + CompatibleId->ProdId); + if (!NT_VERIFY(NT_SUCCESS(Status))) + goto Failure; + + DPRINT(" '%S'\n", IdStart); + + ++End; + --Remaining; + } + + *End = UNICODE_NULL; + + break; + }
case BusQueryInstanceID: { @@ -319,6 +405,64 @@ IsaReadPortQueryId( return STATUS_SUCCESS; }
+static +CODE_SEG("PAGE") +NTSTATUS +IsaPdoQueryDeviceText( + _In_ PISAPNP_PDO_EXTENSION PdoExt, + _Inout_ PIRP Irp, + _In_ PIO_STACK_LOCATION IrpSp) +{ + NTSTATUS Status; + PWCHAR Buffer; + size_t CharCount; + + PAGED_CODE(); + + switch (IrpSp->Parameters.QueryDeviceText.DeviceTextType) + { + case DeviceTextDescription: + { + if (!PdoExt->IsaPnpDevice->FriendlyName) + return Irp->IoStatus.Status; + + CharCount = strlen(PdoExt->IsaPnpDevice->FriendlyName) + + sizeof(ANSI_NULL); + + if (CharCount == sizeof(ANSI_NULL)) + return Irp->IoStatus.Status; + + Buffer = ExAllocatePoolWithTag(PagedPool, + CharCount * sizeof(WCHAR), + TAG_ISAPNP); + if (!Buffer) + return STATUS_INSUFFICIENT_RESOURCES; + + Status = RtlStringCchPrintfExW(Buffer, + CharCount, + NULL, + NULL, + 0, + L"%hs", + PdoExt->IsaPnpDevice->FriendlyName); + if (!NT_VERIFY(NT_SUCCESS(Status))) + { + ExFreePoolWithTag(Buffer, TAG_ISAPNP); + return Status; + } + + DPRINT("TextDescription: '%S'\n", Buffer); + break; + } + + default: + return Irp->IoStatus.Status; + } + + Irp->IoStatus.Information = (ULONG_PTR)Buffer; + return STATUS_SUCCESS; +} + static CODE_SEG("PAGE") NTSTATUS @@ -428,7 +572,7 @@ IsaPdoStartReadPort( SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart;
/* We detected some ISAPNP cards */ - if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort))) + if (IsaHwTryReadDataPort(ReadDataPort) > 0) { SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart; break; @@ -473,7 +617,9 @@ IsaPdoStartReadPort( PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3);
/* Run the isolation protocol */ - if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort))) + FdoExt->Cards = IsaHwTryReadDataPort(ReadDataPort); + + if (FdoExt->Cards > 0) { FdoExt->ReadDataPort = ReadDataPort;
@@ -482,16 +628,13 @@ IsaPdoStartReadPort( /* Card identification */ Status = IsaHwFillDeviceList(FdoExt);
- if (FdoExt->DeviceCount > 0) - { - PdoExt->Flags |= ISAPNP_READ_PORT_ALLOW_FDO_SCAN | - ISAPNP_SCANNED_BY_READ_PORT; + IsaPnpReleaseDeviceDataLock(FdoExt);
- IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations); - IoInvalidateDeviceRelations(FdoExt->ReadPortPdo, RemovalRelations); - } + PdoExt->Flags |= ISAPNP_READ_PORT_ALLOW_FDO_SCAN | + ISAPNP_SCANNED_BY_READ_PORT;
- IsaPnpReleaseDeviceDataLock(FdoExt); + IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations); + IoInvalidateDeviceRelations(FdoExt->ReadPortPdo, RemovalRelations);
return Status; } @@ -653,6 +796,7 @@ IsaPnpRemoveLogicalDeviceDO( { PISAPNP_PDO_EXTENSION PdoExt = Pdo->DeviceExtension; PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice; + PLIST_ENTRY Entry;
PAGED_CODE(); ASSERT(LogDev); @@ -665,6 +809,25 @@ IsaPnpRemoveLogicalDeviceDO( if (PdoExt->ResourceList) ExFreePoolWithTag(PdoExt->ResourceList, TAG_ISAPNP);
+ if (LogDev->FriendlyName) + ExFreePoolWithTag(LogDev->FriendlyName, TAG_ISAPNP); + + if (LogDev->Alternatives) + ExFreePoolWithTag(LogDev->Alternatives, TAG_ISAPNP); + + Entry = LogDev->CompatibleIdList.Flink; + while (Entry != &LogDev->CompatibleIdList) + { + PISAPNP_COMPATIBLE_ID_ENTRY CompatibleId = + CONTAINING_RECORD(Entry, ISAPNP_COMPATIBLE_ID_ENTRY, IdLink); + + RemoveEntryList(&CompatibleId->IdLink); + + Entry = Entry->Flink; + + ExFreePoolWithTag(CompatibleId, TAG_ISAPNP); + } + ExFreePoolWithTag(LogDev, TAG_ISAPNP);
IoDeleteDevice(PdoExt->Common.Self); @@ -790,6 +953,11 @@ IsaPdoPnp( Status = IsaReadPortQueryId(Irp, IrpSp); break;
+ case IRP_MN_QUERY_DEVICE_TEXT: + if (PdoExt->Common.Signature == IsaPnpLogicalDevice) + Status = IsaPdoQueryDeviceText(PdoExt, Irp, IrpSp); + break; + case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: Status = IsaPdoFilterResourceRequirements(PdoExt, Irp, IrpSp); break;