diff --git a/drivers/bus/isapnp/hardware.c b/drivers/bus/isapnp/hardware.c index 9dae1c66eb6..0b6e200478a 100644 --- a/drivers/bus/isapnp/hardware.c +++ b/drivers/bus/isapnp/hardware.c @@ -83,6 +83,17 @@ ReadWord( (ReadByte(ReadDataPort, Address + 1))); } +static +inline +ULONG +ReadDoubleWord( + _In_ PUCHAR ReadDataPort, + _In_ UCHAR Address) +{ + return ((ReadWord(ReadDataPort, Address) << 8) | + (ReadWord(ReadDataPort, Address + 2))); +} + static inline VOID @@ -198,7 +209,7 @@ ReadIrqNo( _In_ PUCHAR ReadDataPort, _In_ UCHAR Index) { - return ReadByte(ReadDataPort, ISAPNP_IRQNO(Index)); + return ReadByte(ReadDataPort, ISAPNP_IRQNO(Index)) & 0x0F; } static @@ -218,7 +229,67 @@ ReadDmaChannel( _In_ PUCHAR ReadDataPort, _In_ UCHAR Index) { - return ReadByte(ReadDataPort, ISAPNP_DMACHANNEL(Index)); + return ReadByte(ReadDataPort, ISAPNP_DMACHANNEL(Index)) & 0x07; +} + +static +inline +USHORT +ReadMemoryBase( + _In_ PUCHAR ReadDataPort, + _In_ UCHAR Index) +{ + return ReadWord(ReadDataPort, ISAPNP_MEMBASE(Index)); +} + +static +inline +UCHAR +ReadMemoryControl( + _In_ PUCHAR ReadDataPort, + _In_ UCHAR Index) +{ + return ReadByte(ReadDataPort, ISAPNP_MEMCONTROL(Index)); +} + +static +inline +USHORT +ReadMemoryLimit( + _In_ PUCHAR ReadDataPort, + _In_ UCHAR Index) +{ + return ReadWord(ReadDataPort, ISAPNP_MEMLIMIT(Index)); +} + +static +inline +ULONG +ReadMemoryBase32( + _In_ PUCHAR ReadDataPort, + _In_ UCHAR Index) +{ + return ReadDoubleWord(ReadDataPort, ISAPNP_MEMBASE32(Index)); +} + +static +inline +UCHAR +ReadMemoryControl32( + _In_ PUCHAR ReadDataPort, + _In_ UCHAR Index) +{ + return ReadByte(ReadDataPort, ISAPNP_MEMCONTROL32(Index)); +} + +static +inline +ULONG +ReadMemoryLimit32( + _In_ PUCHAR ReadDataPort, + _In_ UCHAR Index) +{ + return ReadDoubleWord(ReadDataPort, ISAPNP_MEMLIMIT32(Index)); } static @@ -1016,6 +1087,95 @@ SkipTag: } } +static +CODE_SEG("PAGE") +BOOLEAN +ReadCurrentResources( + _In_ PUCHAR ReadDataPort, + _Inout_ PISAPNP_LOGICAL_DEVICE LogDevice) +{ + UCHAR i; + + PAGED_CODE(); + + DPRINT("%s for CSN %u, LDN %u\n", __FUNCTION__, LogDevice->CSN, LogDevice->LDN); + + WriteLogicalDeviceNumber(LogDevice->LDN); + + /* If the device is not activated by BIOS we just report a NULL resource list */ + if (!(ReadByte(ReadDataPort, ISAPNP_ACTIVATE) & 1)) + { + LogDevice->Flags &= ~ISAPNP_HAS_RESOURCES; + return FALSE; + } + + for (i = 0; i < RTL_NUMBER_OF(LogDevice->Io); i++) + { + LogDevice->Io[i].CurrentBase = ReadIoBase(ReadDataPort, i); + + /* Skip empty descriptors */ + if (!LogDevice->Io[i].CurrentBase) + break; + } + for (i = 0; i < RTL_NUMBER_OF(LogDevice->Irq); i++) + { + LogDevice->Irq[i].CurrentNo = ReadIrqNo(ReadDataPort, i); + + if (!LogDevice->Irq[i].CurrentNo) + break; + + LogDevice->Irq[i].CurrentType = ReadIrqType(ReadDataPort, i); + } + for (i = 0; i < RTL_NUMBER_OF(LogDevice->Dma); i++) + { + LogDevice->Dma[i].CurrentChannel = ReadDmaChannel(ReadDataPort, i); + + if (LogDevice->Dma[i].CurrentChannel == 4) + break; + } + for (i = 0; i < RTL_NUMBER_OF(LogDevice->MemRange); i++) + { + LogDevice->MemRange[i].CurrentBase = ReadMemoryBase(ReadDataPort, i) << 8; + + if (!LogDevice->MemRange[i].CurrentBase) + break; + + LogDevice->MemRange[i].CurrentLength = ReadMemoryLimit(ReadDataPort, i) << 8; + + if (ReadMemoryControl(ReadDataPort, i) & MEMORY_UPPER_LIMIT) + { + LogDevice->MemRange[i].CurrentLength -= LogDevice->MemRange[i].CurrentBase; + } + else + { + LogDevice->MemRange[i].CurrentLength = + RANGE_LENGTH_TO_LENGTH(LogDevice->MemRange[i].CurrentLength); + } + } + for (i = 0; i < RTL_NUMBER_OF(LogDevice->MemRange32); i++) + { + LogDevice->MemRange32[i].CurrentBase = ReadMemoryBase32(ReadDataPort, i); + + if (!LogDevice->MemRange32[i].CurrentBase) + break; + + LogDevice->MemRange32[i].CurrentLength = ReadMemoryLimit32(ReadDataPort, i); + + if (ReadMemoryControl32(ReadDataPort, i) & MEMORY_UPPER_LIMIT) + { + LogDevice->MemRange32[i].CurrentLength -= LogDevice->MemRange32[i].CurrentBase; + } + else + { + LogDevice->MemRange32[i].CurrentLength = + RANGE_LENGTH_TO_LENGTH(LogDevice->MemRange32[i].CurrentLength); + } + } + + LogDevice->Flags |= ISAPNP_HAS_RESOURCES; + return TRUE; +} + static CODE_SEG("PAGE") INT @@ -1153,7 +1313,6 @@ IsaHwFillDeviceList( { PISAPNP_LOGICAL_DEVICE LogDevice; UCHAR Csn; - ULONG i; PLIST_ENTRY Entry; PUCHAR ResourceData; @@ -1264,19 +1423,8 @@ IsaHwFillDeviceList( goto Deactivate; } - WriteLogicalDeviceNumber(LogDev); - - for (i = 0; i < ARRAYSIZE(LogDevice->Io); i++) - LogDevice->Io[i].CurrentBase = ReadIoBase(FdoExt->ReadDataPort, i); - for (i = 0; i < ARRAYSIZE(LogDevice->Irq); i++) - { - LogDevice->Irq[i].CurrentNo = ReadIrqNo(FdoExt->ReadDataPort, i); - LogDevice->Irq[i].CurrentType = ReadIrqType(FdoExt->ReadDataPort, i); - } - for (i = 0; i < ARRAYSIZE(LogDevice->Dma); i++) - { - LogDevice->Dma[i].CurrentChannel = ReadDmaChannel(FdoExt->ReadDataPort, i); - } + if (!ReadCurrentResources(FdoExt->ReadDataPort, LogDevice)) + DPRINT("Unable to read boot resources\n"); IsaPnpExtractAscii(LogDevice->VendorId, Identifier.VendorId); LogDevice->ProdId = Identifier.ProdId; diff --git a/drivers/bus/isapnp/isapnp.h b/drivers/bus/isapnp/isapnp.h index d80d05dced1..3ba3e5032ac 100644 --- a/drivers/bus/isapnp/isapnp.h +++ b/drivers/bus/isapnp/isapnp.h @@ -133,6 +133,7 @@ typedef struct _ISAPNP_LOGICAL_DEVICE 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. */ +#define ISAPNP_HAS_RESOURCES 0x00000004 /**< @brief Cleared when the device has no boot resources. */ LIST_ENTRY DeviceLink; } ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE; diff --git a/drivers/bus/isapnp/isapnphw.h b/drivers/bus/isapnp/isapnphw.h index b3d8021a62c..c41d6d1b7be 100644 --- a/drivers/bus/isapnp/isapnphw.h +++ b/drivers/bus/isapnp/isapnphw.h @@ -28,10 +28,17 @@ extern "C" { #define ISAPNP_ACTIVATE 0x30 #define ISAPNP_IORANGECHECK 0x31 +#define ISAPNP_MEMBASE(n) (0x40 + ((n) * 8)) +#define ISAPNP_MEMCONTROL(n) (0x42 + ((n) * 8)) +#define MEMORY_UPPER_LIMIT 0x01 +#define ISAPNP_MEMLIMIT(n) (0x43 + ((n) * 8)) #define ISAPNP_IOBASE(n) (0x60 + ((n)*2)) #define ISAPNP_IRQNO(n) (0x70 + ((n)*2)) #define ISAPNP_IRQTYPE(n) (0x71 + ((n) * 2)) #define ISAPNP_DMACHANNEL(n) (0x74 + (n)) +#define ISAPNP_MEMBASE32(n) ((n) == 0 ? 0x76 : (0x70 + (n) * 16)) +#define ISAPNP_MEMCONTROL32(n) ((n) == 0 ? 0x7A : (0x74 + (n) * 16)) +#define ISAPNP_MEMLIMIT32(n) ((n) == 0 ? 0x7B : (0x75 + (n) * 16)) #define ISAPNP_CONFIG_RESET (1 << 0) #define ISAPNP_CONFIG_WAIT_FOR_KEY (1 << 1) @@ -61,6 +68,9 @@ extern "C" { #define ISAPNP_TAG_MEM32RANGE 0x85 #define ISAPNP_TAG_FIXEDMEM32RANGE 0x86 +#define RANGE_LENGTH_TO_LENGTH(RangeLength) ((~(RangeLength) + 1) & 0xFFFFFF) +#define LENGTH_TO_RANGE_LENGTH(Length) (~(Length) + 1) + #include typedef struct _ISAPNP_IDENTIFIER diff --git a/drivers/bus/isapnp/pdo.c b/drivers/bus/isapnp/pdo.c index 67a30891ac1..8490bf9c14d 100644 --- a/drivers/bus/isapnp/pdo.c +++ b/drivers/bus/isapnp/pdo.c @@ -478,6 +478,13 @@ IsaPdoQueryResources( PAGED_CODE(); + if (PdoExt->Common.Signature == IsaPnpLogicalDevice && + !(PdoExt->IsaPnpDevice->Flags & ISAPNP_HAS_RESOURCES)) + { + Irp->IoStatus.Information = 0; + return STATUS_SUCCESS; + } + if (!PdoExt->ResourceList) return Irp->IoStatus.Status;