mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[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.
This commit is contained in:
parent
7c897dfbd1
commit
ca42de9c31
5 changed files with 1122 additions and 156 deletions
|
@ -4,6 +4,7 @@
|
||||||
* PURPOSE: Hardware support code
|
* PURPOSE: Hardware support code
|
||||||
* COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
|
* COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
|
||||||
* Copyright 2020 Hervé Poussineau <hpoussin@reactos.org>
|
* Copyright 2020 Hervé Poussineau <hpoussin@reactos.org>
|
||||||
|
* Copyright 2021 Dmitry Borisov <di.sean@protonmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "isapnp.h"
|
#include "isapnp.h"
|
||||||
|
@ -11,6 +12,17 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#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
|
static
|
||||||
inline
|
inline
|
||||||
VOID
|
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
|
static
|
||||||
CODE_SEG("PAGE")
|
CODE_SEG("PAGE")
|
||||||
UCHAR
|
UCHAR
|
||||||
|
@ -318,24 +348,48 @@ IsaPnpChecksum(
|
||||||
|
|
||||||
static
|
static
|
||||||
CODE_SEG("PAGE")
|
CODE_SEG("PAGE")
|
||||||
BOOLEAN
|
VOID
|
||||||
ReadTags(
|
IsaPnpExtractAscii(
|
||||||
_In_ PUCHAR ReadDataPort,
|
_Out_writes_all_(3) PUCHAR Buffer,
|
||||||
_In_ USHORT LogDev,
|
_In_ USHORT CompressedData)
|
||||||
_Inout_ PISAPNP_LOGICAL_DEVICE LogDevice)
|
|
||||||
{
|
{
|
||||||
BOOLEAN res = FALSE;
|
|
||||||
PVOID Buffer;
|
|
||||||
USHORT Tag, TagLen, MaxLen;
|
|
||||||
ULONG NumberOfIo = 0, NumberOfIrq = 0, NumberOfDma = 0;
|
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
LogDev += 1;
|
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,
|
||||||
|
_Out_writes_(ISAPNP_MAX_RESOURCEDATA) PUCHAR Buffer,
|
||||||
|
_In_ ULONG MaxLength,
|
||||||
|
_Out_ PUSHORT MaxLogDev)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
*MaxLogDev = 0;
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
|
UCHAR Tag;
|
||||||
|
USHORT TagLen;
|
||||||
|
|
||||||
|
if (MaxLength < 1)
|
||||||
|
return STATUS_BUFFER_OVERFLOW;
|
||||||
|
|
||||||
Tag = PeekByte(ReadDataPort);
|
Tag = PeekByte(ReadDataPort);
|
||||||
|
if (Tag == 0)
|
||||||
|
{
|
||||||
|
DPRINT("Invalid tag\n");
|
||||||
|
return STATUS_INVALID_PARAMETER_1;
|
||||||
|
}
|
||||||
|
*Buffer++ = Tag;
|
||||||
|
--MaxLength;
|
||||||
|
|
||||||
if (ISAPNP_IS_SMALL_TAG(Tag))
|
if (ISAPNP_IS_SMALL_TAG(Tag))
|
||||||
{
|
{
|
||||||
TagLen = ISAPNP_SMALL_TAG_LEN(Tag);
|
TagLen = ISAPNP_SMALL_TAG_LEN(Tag);
|
||||||
|
@ -343,64 +397,623 @@ ReadTags(
|
||||||
}
|
}
|
||||||
else
|
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);
|
Tag = ISAPNP_LARGE_TAG_NAME(Tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Tag == 0xFF && TagLen == 0xFFFF)
|
||||||
|
{
|
||||||
|
DPRINT("Invalid tag\n");
|
||||||
|
return STATUS_INVALID_PARAMETER_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
if (Tag == ISAPNP_TAG_END)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
Buffer = NULL;
|
return STATUS_SUCCESS;
|
||||||
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))
|
|
||||||
{
|
|
||||||
MaxLen = sizeof(LogDevice->Io[NumberOfIo].Description);
|
|
||||||
Buffer = &LogDevice->Io[NumberOfIo].Description;
|
|
||||||
NumberOfIo++;
|
|
||||||
}
|
|
||||||
else if (Tag == ISAPNP_TAG_DMA && NumberOfDma < ARRAYSIZE(LogDevice->Dma))
|
|
||||||
{
|
|
||||||
MaxLen = sizeof(LogDevice->Dma[NumberOfDma].Description);
|
|
||||||
Buffer = &LogDevice->Dma[NumberOfDma].Description;
|
|
||||||
NumberOfDma++;
|
|
||||||
}
|
|
||||||
else if (LogDev == 0)
|
|
||||||
{
|
|
||||||
DPRINT1("Found unknown tag 0x%x (len %d)\n", Tag, TagLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Buffer && LogDev == 0)
|
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))
|
||||||
{
|
{
|
||||||
res = TRUE;
|
TagLen = ISAPNP_SMALL_TAG_LEN(Tag);
|
||||||
if (MaxLen > TagLen)
|
Tag = ISAPNP_SMALL_TAG_NAME(Tag);
|
||||||
{
|
|
||||||
Peek(ReadDataPort, Buffer, TagLen);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Peek(ReadDataPort, Buffer, MaxLen);
|
|
||||||
Peek(ReadDataPort, NULL, TagLen - MaxLen);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* We don't want to read informations on this
|
TagLen = *ResourceData++;
|
||||||
* logical device, or we don't know the tag. */
|
TagLen += *ResourceData++ << 8;
|
||||||
Peek(ReadDataPort, NULL, TagLen);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return res;
|
Tag = ISAPNP_LARGE_TAG_NAME(Tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Tag)
|
||||||
|
{
|
||||||
|
case ISAPNP_TAG_LOGDEVID:
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ISAPNP_TAG_COMPATDEVID:
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
static
|
||||||
|
@ -532,54 +1145,127 @@ DeviceActivation(
|
||||||
WaitForKey();
|
WaitForKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
_Requires_lock_held_(FdoExt->DeviceSyncEvent)
|
||||||
CODE_SEG("PAGE")
|
CODE_SEG("PAGE")
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
ProbeIsaPnpBus(
|
IsaHwFillDeviceList(
|
||||||
_In_ PISAPNP_FDO_EXTENSION FdoExt)
|
_In_ PISAPNP_FDO_EXTENSION FdoExt)
|
||||||
{
|
{
|
||||||
PISAPNP_LOGICAL_DEVICE LogDevice;
|
PISAPNP_LOGICAL_DEVICE LogDevice;
|
||||||
ISAPNP_IDENTIFIER Identifier;
|
UCHAR Csn;
|
||||||
USHORT Csn;
|
|
||||||
USHORT LogDev;
|
|
||||||
ULONG i;
|
ULONG i;
|
||||||
|
PLIST_ENTRY Entry;
|
||||||
|
PUCHAR ResourceData;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
ASSERT(FdoExt->ReadDataPort);
|
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)
|
||||||
{
|
{
|
||||||
for (LogDev = 0; LogDev <= 0xFF; LogDev++)
|
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++)
|
||||||
|
{
|
||||||
|
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);
|
LogDevice = ExAllocatePoolZero(NonPagedPool, sizeof(ISAPNP_LOGICAL_DEVICE), TAG_ISAPNP);
|
||||||
if (!LogDevice)
|
if (!LogDevice)
|
||||||
return STATUS_NO_MEMORY;
|
{
|
||||||
|
DPRINT1("Failed to allocate logical device!\n");
|
||||||
|
goto Deactivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeListHead(&LogDevice->CompatibleIdList);
|
||||||
|
|
||||||
LogDevice->CSN = Csn;
|
LogDevice->CSN = Csn;
|
||||||
LogDevice->LDN = LogDev;
|
LogDevice->LDN = LogDev;
|
||||||
|
|
||||||
WaitForKey();
|
Status = ParseTags(ResourceData, LogDev, LogDevice);
|
||||||
SendKey();
|
if (!NT_SUCCESS(Status))
|
||||||
Wake(Csn);
|
|
||||||
|
|
||||||
Peek(FdoExt->ReadDataPort, &Identifier, sizeof(Identifier));
|
|
||||||
|
|
||||||
if (Identifier.VendorId & 0x80)
|
|
||||||
{
|
{
|
||||||
ExFreePoolWithTag(LogDevice, TAG_ISAPNP);
|
DPRINT1("Failed to parse tags with status 0x%08lx, CSN %u, LDN %u\n",
|
||||||
return STATUS_SUCCESS;
|
Status, LogDevice->CSN, LogDevice->LDN);
|
||||||
|
FreeLogicalDevice(LogDevice);
|
||||||
|
goto Deactivate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ReadTags(FdoExt->ReadDataPort, LogDev, LogDevice))
|
|
||||||
break;
|
|
||||||
|
|
||||||
WriteLogicalDeviceNumber(LogDev);
|
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++)
|
for (i = 0; i < ARRAYSIZE(LogDevice->Io); i++)
|
||||||
LogDevice->Io[i].CurrentBase = ReadIoBase(FdoExt->ReadDataPort, i);
|
LogDevice->Io[i].CurrentBase = ReadIoBase(FdoExt->ReadDataPort, i);
|
||||||
for (i = 0; i < ARRAYSIZE(LogDevice->Irq); i++)
|
for (i = 0; i < ARRAYSIZE(LogDevice->Irq); i++)
|
||||||
|
@ -592,27 +1278,37 @@ ProbeIsaPnpBus(
|
||||||
LogDevice->Dma[i].CurrentChannel = ReadDmaChannel(FdoExt->ReadDataPort, i);
|
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",
|
IsaPnpExtractAscii(LogDevice->VendorId, Identifier.VendorId);
|
||||||
LogDevice->VendorId, LogDevice->ProdId, LogDevice->SerialNumber, LogDevice->Io[0].CurrentBase, LogDevice->Irq[0].CurrentNo);
|
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);
|
InsertTailList(&FdoExt->DeviceListHead, &LogDevice->DeviceLink);
|
||||||
FdoExt->DeviceCount++;
|
FdoExt->DeviceCount++;
|
||||||
|
|
||||||
|
/* Now we wait for the start device IRP */
|
||||||
|
Deactivate:
|
||||||
|
DeactivateDevice(LogDev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExFreePoolWithTag(ResourceData, TAG_ISAPNP);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
CODE_SEG("PAGE")
|
CODE_SEG("PAGE")
|
||||||
NTSTATUS
|
ULONG
|
||||||
IsaHwTryReadDataPort(
|
IsaHwTryReadDataPort(
|
||||||
_In_ PUCHAR ReadDataPort)
|
_In_ PUCHAR ReadDataPort)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
return TryIsolate(ReadDataPort) > 0 ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
|
return TryIsolate(ReadDataPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||||
|
@ -636,13 +1332,3 @@ IsaHwDeactivateDevice(
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
CODE_SEG("PAGE")
|
|
||||||
NTSTATUS
|
|
||||||
IsaHwFillDeviceList(
|
|
||||||
_In_ PISAPNP_FDO_EXTENSION FdoExt)
|
|
||||||
{
|
|
||||||
PAGED_CODE();
|
|
||||||
|
|
||||||
return ProbeIsaPnpBus(FdoExt);
|
|
||||||
}
|
|
||||||
|
|
|
@ -676,11 +676,11 @@ IsaPnpFillDeviceRelations(
|
||||||
DPRINT("Rescan ISA PnP bus\n");
|
DPRINT("Rescan ISA PnP bus\n");
|
||||||
|
|
||||||
/* Run the isolation protocol */
|
/* Run the isolation protocol */
|
||||||
if (NT_SUCCESS(IsaHwTryReadDataPort(FdoExt->ReadDataPort)))
|
FdoExt->Cards = IsaHwTryReadDataPort(FdoExt->ReadDataPort);
|
||||||
{
|
|
||||||
/* Card identification */
|
/* Card identification */
|
||||||
|
if (FdoExt->Cards > 0)
|
||||||
(VOID)IsaHwFillDeviceList(FdoExt);
|
(VOID)IsaHwFillDeviceList(FdoExt);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadPortExt->Flags &= ~ISAPNP_SCANNED_BY_READ_PORT;
|
ReadPortExt->Flags &= ~ISAPNP_SCANNED_BY_READ_PORT;
|
||||||
|
|
|
@ -23,6 +23,12 @@ extern "C" {
|
||||||
|
|
||||||
#define TAG_ISAPNP 'pasI'
|
#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
|
typedef enum
|
||||||
{
|
{
|
||||||
dsStopped,
|
dsStopped,
|
||||||
|
@ -33,6 +39,7 @@ typedef struct _ISAPNP_IO
|
||||||
{
|
{
|
||||||
USHORT CurrentBase;
|
USHORT CurrentBase;
|
||||||
ISAPNP_IO_DESCRIPTION Description;
|
ISAPNP_IO_DESCRIPTION Description;
|
||||||
|
UCHAR Index;
|
||||||
} ISAPNP_IO, *PISAPNP_IO;
|
} ISAPNP_IO, *PISAPNP_IO;
|
||||||
|
|
||||||
typedef struct _ISAPNP_IRQ
|
typedef struct _ISAPNP_IRQ
|
||||||
|
@ -40,29 +47,92 @@ typedef struct _ISAPNP_IRQ
|
||||||
UCHAR CurrentNo;
|
UCHAR CurrentNo;
|
||||||
UCHAR CurrentType;
|
UCHAR CurrentType;
|
||||||
ISAPNP_IRQ_DESCRIPTION Description;
|
ISAPNP_IRQ_DESCRIPTION Description;
|
||||||
|
UCHAR Index;
|
||||||
} ISAPNP_IRQ, *PISAPNP_IRQ;
|
} ISAPNP_IRQ, *PISAPNP_IRQ;
|
||||||
|
|
||||||
typedef struct _ISAPNP_DMA
|
typedef struct _ISAPNP_DMA
|
||||||
{
|
{
|
||||||
UCHAR CurrentChannel;
|
UCHAR CurrentChannel;
|
||||||
ISAPNP_DMA_DESCRIPTION Description;
|
ISAPNP_DMA_DESCRIPTION Description;
|
||||||
|
UCHAR Index;
|
||||||
} ISAPNP_DMA, *PISAPNP_DMA;
|
} 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
|
typedef struct _ISAPNP_LOGICAL_DEVICE
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT Pdo;
|
PDEVICE_OBJECT Pdo;
|
||||||
ISAPNP_LOGDEVID LogDevId;
|
|
||||||
|
/**
|
||||||
|
* @name The card data.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
UCHAR CSN;
|
||||||
UCHAR VendorId[3];
|
UCHAR VendorId[3];
|
||||||
USHORT ProdId;
|
USHORT ProdId;
|
||||||
ULONG SerialNumber;
|
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_IO Io[8];
|
||||||
ISAPNP_IRQ Irq[2];
|
ISAPNP_IRQ Irq[2];
|
||||||
ISAPNP_DMA Dma[2];
|
ISAPNP_DMA Dma[2];
|
||||||
UCHAR CSN;
|
ISAPNP_MEMRANGE MemRange[4];
|
||||||
UCHAR LDN;
|
ISAPNP_MEMRANGE32 MemRange32[4];
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
ULONG Flags;
|
ULONG Flags;
|
||||||
#define ISAPNP_PRESENT 0x00000001 /**< @brief Cleared when the device is physically removed. */
|
#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;
|
LIST_ENTRY DeviceLink;
|
||||||
} ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE;
|
} ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE;
|
||||||
|
@ -98,6 +168,7 @@ typedef struct _ISAPNP_FDO_EXTENSION
|
||||||
|
|
||||||
PDRIVER_OBJECT DriverObject;
|
PDRIVER_OBJECT DriverObject;
|
||||||
PUCHAR ReadDataPort;
|
PUCHAR ReadDataPort;
|
||||||
|
ULONG Cards;
|
||||||
LIST_ENTRY BusLink;
|
LIST_ENTRY BusLink;
|
||||||
} ISAPNP_FDO_EXTENSION, *PISAPNP_FDO_EXTENSION;
|
} ISAPNP_FDO_EXTENSION, *PISAPNP_FDO_EXTENSION;
|
||||||
|
|
||||||
|
@ -165,6 +236,46 @@ IsaPnpReleaseDeviceDataLock(
|
||||||
KeSetEvent(&FdoExt->DeviceSyncEvent, IO_NO_INCREMENT, FALSE);
|
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 */
|
/* isapnp.c */
|
||||||
|
|
||||||
CODE_SEG("PAGE")
|
CODE_SEG("PAGE")
|
||||||
|
@ -218,10 +329,11 @@ IsaPnpRemoveLogicalDeviceDO(
|
||||||
|
|
||||||
/* hardware.c */
|
/* hardware.c */
|
||||||
CODE_SEG("PAGE")
|
CODE_SEG("PAGE")
|
||||||
NTSTATUS
|
ULONG
|
||||||
IsaHwTryReadDataPort(
|
IsaHwTryReadDataPort(
|
||||||
_In_ PUCHAR ReadDataPort);
|
_In_ PUCHAR ReadDataPort);
|
||||||
|
|
||||||
|
_Requires_lock_held_(FdoExt->DeviceSyncEvent)
|
||||||
CODE_SEG("PAGE")
|
CODE_SEG("PAGE")
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
IsaHwFillDeviceList(
|
IsaHwFillDeviceList(
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* PURPOSE: Hardware definitions
|
* PURPOSE: Hardware definitions
|
||||||
* COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
|
* COPYRIGHT: Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
|
||||||
* Copyright 2020 Hervé Poussineau <hpoussin@reactos.org>
|
* Copyright 2020 Hervé Poussineau <hpoussin@reactos.org>
|
||||||
|
* Copyright 2021 Dmitry Borisov <di.sean@protonmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -15,14 +16,6 @@ extern "C" {
|
||||||
#define ISAPNP_ADDRESS 0x279
|
#define ISAPNP_ADDRESS 0x279
|
||||||
#define ISAPNP_WRITE_DATA 0xA79
|
#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_READPORT 0x00
|
||||||
#define ISAPNP_SERIALISOLATION 0x01
|
#define ISAPNP_SERIALISOLATION 0x01
|
||||||
#define ISAPNP_CONFIGCONTROL 0x02
|
#define ISAPNP_CONFIGCONTROL 0x02
|
||||||
|
@ -58,11 +51,6 @@ extern "C" {
|
||||||
#define ISAPNP_TAG_ENDDEP 0x07
|
#define ISAPNP_TAG_ENDDEP 0x07
|
||||||
#define ISAPNP_TAG_IOPORT 0x08
|
#define ISAPNP_TAG_IOPORT 0x08
|
||||||
#define ISAPNP_TAG_FIXEDIO 0x09
|
#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_TAG_END 0x0F
|
||||||
|
|
||||||
#define ISAPNP_IS_LARGE_TAG(t) (((t) & 0x80))
|
#define ISAPNP_IS_LARGE_TAG(t) (((t) & 0x80))
|
||||||
|
@ -70,26 +58,10 @@ extern "C" {
|
||||||
#define ISAPNP_TAG_MEMRANGE 0x81
|
#define ISAPNP_TAG_MEMRANGE 0x81
|
||||||
#define ISAPNP_TAG_ANSISTR 0x82
|
#define ISAPNP_TAG_ANSISTR 0x82
|
||||||
#define ISAPNP_TAG_UNICODESTR 0x83
|
#define ISAPNP_TAG_UNICODESTR 0x83
|
||||||
#define ISAPNP_TAG_VENDORLONG 0x84
|
|
||||||
#define ISAPNP_TAG_MEM32RANGE 0x85
|
#define ISAPNP_TAG_MEM32RANGE 0x85
|
||||||
#define ISAPNP_TAG_FIXEDMEM32RANGE 0x86
|
#define ISAPNP_TAG_FIXEDMEM32RANGE 0x86
|
||||||
#define ISAPNP_TAG_RSVDLONG0 0xF0
|
|
||||||
#define ISAPNP_TAG_RSVDLONG1 0xF1
|
#include <pshpack1.h>
|
||||||
#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
|
|
||||||
|
|
||||||
typedef struct _ISAPNP_IDENTIFIER
|
typedef struct _ISAPNP_IDENTIFIER
|
||||||
{
|
{
|
||||||
|
@ -106,14 +78,11 @@ typedef struct _ISAPNP_LOGDEVID
|
||||||
USHORT Flags;
|
USHORT Flags;
|
||||||
} ISAPNP_LOGDEVID, *PISAPNP_LOGDEVID;
|
} ISAPNP_LOGDEVID, *PISAPNP_LOGDEVID;
|
||||||
|
|
||||||
typedef struct _ISAPNP_DEVICEID
|
typedef struct _ISAPNP_COMPATID
|
||||||
{
|
{
|
||||||
CHAR* Name;
|
|
||||||
USHORT VendorId;
|
USHORT VendorId;
|
||||||
USHORT ProdId;
|
USHORT ProdId;
|
||||||
} ISAPNP_DEVICEID, *PISAPNP_DEVICEID;
|
} ISAPNP_COMPATID, *PISAPNP_COMPATID;
|
||||||
|
|
||||||
#include <pshpack1.h>
|
|
||||||
|
|
||||||
typedef struct _ISAPNP_IO_DESCRIPTION
|
typedef struct _ISAPNP_IO_DESCRIPTION
|
||||||
{
|
{
|
||||||
|
@ -124,6 +93,12 @@ typedef struct _ISAPNP_IO_DESCRIPTION
|
||||||
UCHAR Length;
|
UCHAR Length;
|
||||||
} ISAPNP_IO_DESCRIPTION, *PISAPNP_IO_DESCRIPTION;
|
} 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
|
typedef struct _ISAPNP_IRQ_DESCRIPTION
|
||||||
{
|
{
|
||||||
USHORT Mask;
|
USHORT Mask;
|
||||||
|
@ -136,6 +111,31 @@ typedef struct _ISAPNP_DMA_DESCRIPTION
|
||||||
UCHAR Information;
|
UCHAR Information;
|
||||||
} ISAPNP_DMA_DESCRIPTION, *PISAPNP_DMA_DESCRIPTION;
|
} 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>
|
#include <poppack.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -130,6 +130,11 @@ IsaPdoQueryId(
|
||||||
{
|
{
|
||||||
CharCount = sizeof("ISAPNP\\XXXFFFF");
|
CharCount = sizeof("ISAPNP\\XXXFFFF");
|
||||||
|
|
||||||
|
if (LogDev->Flags & ISAPNP_HAS_MULTIPLE_LOGDEVS)
|
||||||
|
{
|
||||||
|
CharCount += sizeof("_DEV1234") - sizeof(ANSI_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
Buffer = ExAllocatePoolWithTag(PagedPool,
|
Buffer = ExAllocatePoolWithTag(PagedPool,
|
||||||
CharCount * sizeof(WCHAR),
|
CharCount * sizeof(WCHAR),
|
||||||
TAG_ISAPNP);
|
TAG_ISAPNP);
|
||||||
|
@ -147,6 +152,19 @@ IsaPdoQueryId(
|
||||||
if (!NT_VERIFY(NT_SUCCESS(Status)))
|
if (!NT_VERIFY(NT_SUCCESS(Status)))
|
||||||
goto Failure;
|
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);
|
DPRINT("Device ID: '%S'\n", Buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -157,6 +175,11 @@ IsaPdoQueryId(
|
||||||
sizeof("*PNPxxxx") +
|
sizeof("*PNPxxxx") +
|
||||||
sizeof(ANSI_NULL); /* multi-string */
|
sizeof(ANSI_NULL); /* multi-string */
|
||||||
|
|
||||||
|
if (LogDev->Flags & ISAPNP_HAS_MULTIPLE_LOGDEVS)
|
||||||
|
{
|
||||||
|
CharCount += sizeof("_DEV1234") - sizeof(ANSI_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
Buffer = ExAllocatePoolWithTag(PagedPool,
|
Buffer = ExAllocatePoolWithTag(PagedPool,
|
||||||
CharCount * sizeof(WCHAR),
|
CharCount * sizeof(WCHAR),
|
||||||
TAG_ISAPNP);
|
TAG_ISAPNP);
|
||||||
|
@ -177,6 +200,19 @@ IsaPdoQueryId(
|
||||||
if (!NT_VERIFY(NT_SUCCESS(Status)))
|
if (!NT_VERIFY(NT_SUCCESS(Status)))
|
||||||
goto Failure;
|
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);
|
DPRINT(" '%S'\n", Buffer);
|
||||||
|
|
||||||
++End;
|
++End;
|
||||||
|
@ -190,8 +226,8 @@ IsaPdoQueryId(
|
||||||
&Remaining,
|
&Remaining,
|
||||||
0,
|
0,
|
||||||
L"*%.3S%04x",
|
L"*%.3S%04x",
|
||||||
LogDev->VendorId,
|
LogDev->LogVendorId,
|
||||||
LogDev->ProdId);
|
LogDev->LogProdId);
|
||||||
if (!NT_VERIFY(NT_SUCCESS(Status)))
|
if (!NT_VERIFY(NT_SUCCESS(Status)))
|
||||||
goto Failure;
|
goto Failure;
|
||||||
|
|
||||||
|
@ -204,7 +240,57 @@ IsaPdoQueryId(
|
||||||
}
|
}
|
||||||
|
|
||||||
case BusQueryCompatibleIDs:
|
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:
|
case BusQueryInstanceID:
|
||||||
{
|
{
|
||||||
|
@ -319,6 +405,64 @@ IsaReadPortQueryId(
|
||||||
return STATUS_SUCCESS;
|
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
|
static
|
||||||
CODE_SEG("PAGE")
|
CODE_SEG("PAGE")
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -428,7 +572,7 @@ IsaPdoStartReadPort(
|
||||||
SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart;
|
SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart;
|
||||||
|
|
||||||
/* We detected some ISAPNP cards */
|
/* We detected some ISAPNP cards */
|
||||||
if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort)))
|
if (IsaHwTryReadDataPort(ReadDataPort) > 0)
|
||||||
{
|
{
|
||||||
SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart;
|
SelectedPort = PartialDescriptor->u.Port.Start.u.LowPart;
|
||||||
break;
|
break;
|
||||||
|
@ -473,7 +617,9 @@ IsaPdoStartReadPort(
|
||||||
PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3);
|
PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3);
|
||||||
|
|
||||||
/* Run the isolation protocol */
|
/* Run the isolation protocol */
|
||||||
if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort)))
|
FdoExt->Cards = IsaHwTryReadDataPort(ReadDataPort);
|
||||||
|
|
||||||
|
if (FdoExt->Cards > 0)
|
||||||
{
|
{
|
||||||
FdoExt->ReadDataPort = ReadDataPort;
|
FdoExt->ReadDataPort = ReadDataPort;
|
||||||
|
|
||||||
|
@ -482,17 +628,14 @@ IsaPdoStartReadPort(
|
||||||
/* Card identification */
|
/* Card identification */
|
||||||
Status = IsaHwFillDeviceList(FdoExt);
|
Status = IsaHwFillDeviceList(FdoExt);
|
||||||
|
|
||||||
if (FdoExt->DeviceCount > 0)
|
|
||||||
{
|
|
||||||
PdoExt->Flags |= ISAPNP_READ_PORT_ALLOW_FDO_SCAN |
|
|
||||||
ISAPNP_SCANNED_BY_READ_PORT;
|
|
||||||
|
|
||||||
IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations);
|
|
||||||
IoInvalidateDeviceRelations(FdoExt->ReadPortPdo, RemovalRelations);
|
|
||||||
}
|
|
||||||
|
|
||||||
IsaPnpReleaseDeviceDataLock(FdoExt);
|
IsaPnpReleaseDeviceDataLock(FdoExt);
|
||||||
|
|
||||||
|
PdoExt->Flags |= ISAPNP_READ_PORT_ALLOW_FDO_SCAN |
|
||||||
|
ISAPNP_SCANNED_BY_READ_PORT;
|
||||||
|
|
||||||
|
IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations);
|
||||||
|
IoInvalidateDeviceRelations(FdoExt->ReadPortPdo, RemovalRelations);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -653,6 +796,7 @@ IsaPnpRemoveLogicalDeviceDO(
|
||||||
{
|
{
|
||||||
PISAPNP_PDO_EXTENSION PdoExt = Pdo->DeviceExtension;
|
PISAPNP_PDO_EXTENSION PdoExt = Pdo->DeviceExtension;
|
||||||
PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice;
|
PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice;
|
||||||
|
PLIST_ENTRY Entry;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
ASSERT(LogDev);
|
ASSERT(LogDev);
|
||||||
|
@ -665,6 +809,25 @@ IsaPnpRemoveLogicalDeviceDO(
|
||||||
if (PdoExt->ResourceList)
|
if (PdoExt->ResourceList)
|
||||||
ExFreePoolWithTag(PdoExt->ResourceList, TAG_ISAPNP);
|
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);
|
ExFreePoolWithTag(LogDev, TAG_ISAPNP);
|
||||||
|
|
||||||
IoDeleteDevice(PdoExt->Common.Self);
|
IoDeleteDevice(PdoExt->Common.Self);
|
||||||
|
@ -790,6 +953,11 @@ IsaPdoPnp(
|
||||||
Status = IsaReadPortQueryId(Irp, IrpSp);
|
Status = IsaReadPortQueryId(Irp, IrpSp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IRP_MN_QUERY_DEVICE_TEXT:
|
||||||
|
if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
|
||||||
|
Status = IsaPdoQueryDeviceText(PdoExt, Irp, IrpSp);
|
||||||
|
break;
|
||||||
|
|
||||||
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
|
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
|
||||||
Status = IsaPdoFilterResourceRequirements(PdoExt, Irp, IrpSp);
|
Status = IsaPdoFilterResourceRequirements(PdoExt, Irp, IrpSp);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue