[ISAPNP] Refactor the configuration code

- Remove useless checks
- Increase code readability
This commit is contained in:
Dmitry Borisov 2024-05-03 20:42:21 +06:00
parent 76ec8411a4
commit 2981e63a31
3 changed files with 168 additions and 181 deletions

View file

@ -1079,7 +1079,7 @@ ReadCurrentResources(
{
LogDevice->Dma[i].CurrentChannel = ReadDmaChannel(ReadDataPort, i);
if (LogDevice->Dma[i].CurrentChannel == 4)
if (LogDevice->Dma[i].CurrentChannel == DMACHANNEL_NONE)
break;
}
for (i = 0; i < RTL_NUMBER_OF(LogDevice->MemRange); i++)
@ -1128,165 +1128,119 @@ ReadCurrentResources(
static
CODE_SEG("PAGE")
VOID
WriteResources(
_In_ PUCHAR ReadDataPort,
_In_ PISAPNP_LOGICAL_DEVICE LogDevice,
_In_ PCM_PARTIAL_RESOURCE_LIST PartialResourceList)
IsaProgramIoDecoder(
_In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
_In_ UCHAR Index)
{
UCHAR i,
NumberOfIo = 0,
NumberOfIrq = 0,
NumberOfDma = 0,
NumberOfMemory = 0,
NumberOfMemory32 = 0;
PAGED_CODE();
ASSERT(Descriptor->u.Port.Start.QuadPart <= 0xFFFF);
WriteWord(ISAPNP_IOBASE(Index), Descriptor->u.Port.Start.LowPart);
}
static
CODE_SEG("PAGE")
VOID
IsaProgramIrqSelect(
_In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
_In_ UCHAR Index)
{
UCHAR TypeSelect;
PAGED_CODE();
WriteLogicalDeviceNumber(LogDevice->LDN);
ASSERT(Descriptor->u.Interrupt.Level <= 15);
for (i = 0; i < PartialResourceList->Count; i++)
if (Descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
TypeSelect = IRQTYPE_HIGH_EDGE;
else
TypeSelect = IRQTYPE_LOW_LEVEL;
WriteByte(ISAPNP_IRQNO(Index), Descriptor->u.Interrupt.Level);
WriteByte(ISAPNP_IRQTYPE(Index), TypeSelect);
}
static
CODE_SEG("PAGE")
VOID
IsaProgramDmaSelect(
_In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
_In_ UCHAR Index)
{
PAGED_CODE();
ASSERT(Descriptor->u.Dma.Channel <= 7);
WriteByte(ISAPNP_DMACHANNEL(Index), Descriptor->u.Dma.Channel);
}
static
CODE_SEG("PAGE")
NTSTATUS
IsaProgramMemoryDecoder(
_In_ PUCHAR ReadDataPort,
_In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
_In_ BOOLEAN IsMemory32,
_In_ UCHAR Information,
_In_ UCHAR Index)
{
UCHAR MemoryControl;
ULONG LengthLimit;
PAGED_CODE();
if (!IsMemory32)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &PartialResourceList->PartialDescriptors[i];
/* The 24-bit memory address decoder always considers bits 0:7 to be zeros */
if (Descriptor->u.Memory.Start.LowPart & 0xFF)
return STATUS_INVALID_PARAMETER;
switch (Descriptor->Type)
if (Information & MEMRANGE_16_BIT_MEMORY_MASK)
MemoryControl = MEMORY_USE_16_BIT_DECODER;
else
MemoryControl = MEMORY_USE_8_BIT_DECODER;
if (ReadMemoryControl(ReadDataPort, Index) & MEMORY_UPPER_LIMIT)
{
case CmResourceTypePort:
{
(VOID)FindIoDescriptor(LogDevice,
0,
Descriptor->u.Port.Start.LowPart,
Descriptor->u.Port.Start.LowPart +
Descriptor->u.Port.Length - 1,
NULL,
NULL);
WriteWord(ISAPNP_IOBASE(NumberOfIo), (USHORT)Descriptor->u.Port.Start.LowPart);
++NumberOfIo;
break;
}
case CmResourceTypeInterrupt:
{
(VOID)FindIrqDescriptor(LogDevice, Descriptor->u.Interrupt.Level);
WriteByte(ISAPNP_IRQNO(NumberOfIrq), (UCHAR)Descriptor->u.Interrupt.Level);
WriteByte(ISAPNP_IRQTYPE(NumberOfIrq),
Descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED
? IRQTYPE_HIGH_EDGE : IRQTYPE_LOW_LEVEL);
++NumberOfIrq;
break;
}
case CmResourceTypeDma:
{
(VOID)FindDmaDescriptor(LogDevice, Descriptor->u.Dma.Channel);
WriteByte(ISAPNP_DMACHANNEL(NumberOfDma), (UCHAR)Descriptor->u.Dma.Channel);
++NumberOfDma;
break;
}
case CmResourceTypeMemory:
{
UCHAR Information;
UCHAR MemoryControl = MEMORY_USE_8_BIT_DECODER;
(VOID)FindMemoryDescriptor(LogDevice,
Descriptor->u.Memory.Start.LowPart,
Descriptor->u.Memory.Start.LowPart +
Descriptor->u.Memory.Length - 1,
&Information);
if (LogicalDevice->Flags & ISAPNP_HAS_MEM24_DECODER)
{
if (Information & MEMRANGE_16_BIT_MEMORY_MASK)
MemoryControl = MEMORY_USE_16_BIT_DECODER;
WriteWord(ISAPNP_MEMBASE(NumberOfMemory),
(USHORT)(Descriptor->u.Memory.Start.LowPart >> 8));
if (ReadMemoryControl(ReadDataPort, NumberOfMemory) & MEMORY_UPPER_LIMIT)
{
WriteByte(ISAPNP_MEMCONTROL(NumberOfMemory),
MemoryControl | MEMORY_UPPER_LIMIT);
WriteWord(ISAPNP_MEMLIMIT(NumberOfMemory),
(USHORT)((Descriptor->u.Memory.Start.LowPart +
Descriptor->u.Memory.Length) >> 8));
}
else
{
WriteByte(ISAPNP_MEMCONTROL(NumberOfMemory), MemoryControl);
WriteWord(ISAPNP_MEMLIMIT(NumberOfMemory),
(USHORT)(LENGTH_TO_RANGE_LENGTH(Descriptor->
u.Memory.Length) >> 8));
}
++NumberOfMemory;
}
else
{
WriteDoubleWord(ISAPNP_MEMBASE32(NumberOfMemory32),
Descriptor->u.Memory.Start.LowPart);
if ((Information & MEMRANGE_16_BIT_MEMORY_MASK) == MEMRANGE_32_BIT_MEMORY_ONLY)
MemoryControl = MEMORY_USE_32_BIT_DECODER;
else if (Information & MEMRANGE_16_BIT_MEMORY_MASK)
MemoryControl = MEMORY_USE_16_BIT_DECODER;
if (ReadMemoryControl32(ReadDataPort, NumberOfMemory32) & MEMORY_UPPER_LIMIT)
{
WriteByte(ISAPNP_MEMCONTROL32(NumberOfMemory32),
MemoryControl | MEMORY_UPPER_LIMIT);
WriteDoubleWord(ISAPNP_MEMLIMIT32(NumberOfMemory32),
Descriptor->u.Memory.Start.LowPart +
Descriptor->u.Memory.Length);
}
else
{
WriteByte(ISAPNP_MEMCONTROL32(NumberOfMemory32), MemoryControl);
WriteDoubleWord(ISAPNP_MEMLIMIT32(NumberOfMemory32),
LENGTH_TO_RANGE_LENGTH(Descriptor->u.Memory.Length));
}
++NumberOfMemory32;
}
break;
}
default:
break;
MemoryControl |= MEMORY_UPPER_LIMIT;
LengthLimit = Descriptor->u.Memory.Start.LowPart + Descriptor->u.Memory.Length;
}
else
{
LengthLimit = LENGTH_TO_RANGE_LENGTH(Descriptor->u.Memory.Length);
}
LengthLimit >>= 8;
WriteWord(ISAPNP_MEMBASE(Index), Descriptor->u.Memory.Start.LowPart >> 8);
WriteByte(ISAPNP_MEMCONTROL(Index), MemoryControl);
WriteWord(ISAPNP_MEMLIMIT(Index), LengthLimit);
}
else
{
if ((Information & MEMRANGE_16_BIT_MEMORY_MASK) == MEMRANGE_32_BIT_MEMORY_ONLY)
MemoryControl = MEMORY_USE_32_BIT_DECODER;
else if (Information & MEMRANGE_16_BIT_MEMORY_MASK)
MemoryControl = MEMORY_USE_16_BIT_DECODER;
else
MemoryControl = MEMORY_USE_8_BIT_DECODER;
if (ReadMemoryControl32(ReadDataPort, Index) & MEMORY_UPPER_LIMIT)
{
MemoryControl |= MEMORY_UPPER_LIMIT;
LengthLimit = Descriptor->u.Memory.Start.LowPart + Descriptor->u.Memory.Length;
}
else
{
LengthLimit = LENGTH_TO_RANGE_LENGTH(Descriptor->u.Memory.Length);
}
WriteDoubleWord(ISAPNP_MEMBASE32(Index), Descriptor->u.Memory.Start.LowPart);
WriteByte(ISAPNP_MEMCONTROL32(Index), MemoryControl);
WriteDoubleWord(ISAPNP_MEMLIMIT32(Index), LengthLimit);
}
for (i = NumberOfIo; i < RTL_NUMBER_OF(LogDevice->Io); i++)
{
WriteWord(ISAPNP_IOBASE(i), 0);
}
for (i = NumberOfIrq; i < RTL_NUMBER_OF(LogDevice->Irq); i++)
{
WriteByte(ISAPNP_IRQNO(i), 0);
WriteByte(ISAPNP_IRQTYPE(i), 0);
}
for (i = NumberOfDma; i < RTL_NUMBER_OF(LogDevice->Dma); i++)
{
WriteByte(ISAPNP_DMACHANNEL(i), 4);
}
for (i = NumberOfMemory; i < RTL_NUMBER_OF(LogDevice->MemRange); i++)
{
WriteWord(ISAPNP_MEMBASE(i), 0);
WriteByte(ISAPNP_MEMCONTROL(i), 0);
WriteWord(ISAPNP_MEMLIMIT(i), 0);
}
for (i = NumberOfMemory32; i < RTL_NUMBER_OF(LogDevice->MemRange32); i++)
{
WriteDoubleWord(ISAPNP_MEMBASE32(i), 0);
WriteByte(ISAPNP_MEMCONTROL32(i), 0);
WriteDoubleWord(ISAPNP_MEMLIMIT32(i), 0);
}
return STATUS_SUCCESS;
}
CODE_SEG("PAGE")
@ -1554,18 +1508,20 @@ IsaHwConfigureDevice(
_In_ PISAPNP_LOGICAL_DEVICE LogicalDevice,
_In_ PCM_RESOURCE_LIST Resources)
{
UCHAR i,
NumberOfIo = 0,
ULONG i;
UCHAR NumberOfIo = 0,
NumberOfIrq = 0,
NumberOfDma = 0,
NumberOfMemory = 0;
NumberOfMemory = 0,
NumberOfMemory32 = 0;
PAGED_CODE();
if (!Resources)
return STATUS_INSUFFICIENT_RESOURCES;
/* Validate the resource list */
WriteLogicalDeviceNumber(LogicalDevice->LDN);
for (i = 0; i < Resources->List[0].PartialResourceList.Count; i++)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor =
@ -1575,63 +1531,68 @@ IsaHwConfigureDevice(
{
case CmResourceTypePort:
{
if (++NumberOfIo > RTL_NUMBER_OF(LogicalDevice->Io))
if (NumberOfIo >= RTL_NUMBER_OF(LogicalDevice->Io))
return STATUS_INVALID_PARAMETER_1;
if (!FindIoDescriptor(LogicalDevice,
0,
Descriptor->u.Port.Start.LowPart,
Descriptor->u.Port.Start.LowPart +
Descriptor->u.Port.Length - 1,
NULL,
NULL))
{
return STATUS_RESOURCE_DATA_NOT_FOUND;
}
IsaProgramIoDecoder(Descriptor, NumberOfIo++);
break;
}
case CmResourceTypeInterrupt:
{
if (++NumberOfIrq > RTL_NUMBER_OF(LogicalDevice->Irq))
if (NumberOfIrq >= RTL_NUMBER_OF(LogicalDevice->Irq))
return STATUS_INVALID_PARAMETER_2;
if (!FindIrqDescriptor(LogicalDevice, Descriptor->u.Interrupt.Level))
return STATUS_RESOURCE_DATA_NOT_FOUND;
IsaProgramIrqSelect(Descriptor, NumberOfIrq++);
break;
}
case CmResourceTypeDma:
{
if (++NumberOfDma > RTL_NUMBER_OF(LogicalDevice->Dma))
if (NumberOfDma >= RTL_NUMBER_OF(LogicalDevice->Dma))
return STATUS_INVALID_PARAMETER_3;
if (!FindDmaDescriptor(LogicalDevice, Descriptor->u.Dma.Channel))
return STATUS_RESOURCE_DATA_NOT_FOUND;
IsaProgramDmaSelect(Descriptor, NumberOfDma++);
break;
}
case CmResourceTypeMemory:
{
BOOLEAN Memory32;
BOOLEAN IsMemory32;
UCHAR Index, Information;
NTSTATUS Status;
if (++NumberOfMemory > RTL_NUMBER_OF(LogicalDevice->MemRange))
if ((NumberOfMemory + NumberOfMemory32) >= RTL_NUMBER_OF(LogicalDevice->MemRange))
return STATUS_INVALID_PARAMETER_4;
/*
* The PNP ROM provides an information byte for each memory descriptor
* which is then used to program the memory control register.
*/
if (!FindMemoryDescriptor(LogicalDevice,
Descriptor->u.Memory.Start.LowPart,
Descriptor->u.Memory.Start.LowPart +
Descriptor->u.Memory.Length - 1,
NULL))
&Information))
{
return STATUS_RESOURCE_DATA_NOT_FOUND;
}
if ((LogicalDevice->Flags & ISAPNP_HAS_MEM24_DECODER) && (Descriptor->u.Memory.Start.LowPart & 0xFF))
return STATUS_INVALID_PARAMETER;
/* We can have a 24- or 32-bit memory decoder, but not both */
IsMemory32 = !!(LogicalDevice->Flags & ISAPNP_HAS_MEM32_DECODER);
if (IsMemory32)
Index = NumberOfMemory32++;
else
Index = NumberOfMemory++;
Status = IsaProgramMemoryDecoder(FdoExt->ReadDataPort,
Descriptor,
IsMemory32,
Information,
Index);
if (!NT_SUCCESS(Status))
return Status;
break;
}
@ -1641,7 +1602,32 @@ IsaHwConfigureDevice(
}
}
WriteResources(FdoExt->ReadDataPort, LogicalDevice, &Resources->List[0].PartialResourceList);
/* Disable the unclaimed device resources */
for (i = NumberOfIo; i < RTL_NUMBER_OF(LogicalDevice->Io); i++)
{
WriteWord(ISAPNP_IOBASE(i), 0);
}
for (i = NumberOfIrq; i < RTL_NUMBER_OF(LogicalDevice->Irq); i++)
{
WriteByte(ISAPNP_IRQNO(i), 0);
WriteByte(ISAPNP_IRQTYPE(i), 0);
}
for (i = NumberOfDma; i < RTL_NUMBER_OF(LogicalDevice->Dma); i++)
{
WriteByte(ISAPNP_DMACHANNEL(i), DMACHANNEL_NONE);
}
for (i = NumberOfMemory; i < RTL_NUMBER_OF(LogicalDevice->MemRange); i++)
{
WriteWord(ISAPNP_MEMBASE(i), 0);
WriteByte(ISAPNP_MEMCONTROL(i), 0);
WriteWord(ISAPNP_MEMLIMIT(i), 0);
}
for (i = NumberOfMemory32; i < RTL_NUMBER_OF(LogicalDevice->MemRange32); i++)
{
WriteDoubleWord(ISAPNP_MEMBASE32(i), 0);
WriteByte(ISAPNP_MEMCONTROL32(i), 0);
WriteDoubleWord(ISAPNP_MEMLIMIT32(i), 0);
}
KeStallExecutionProcessor(10000);

View file

@ -652,7 +652,7 @@ IsaPnpCreateLogicalDeviceResources(
}
for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++)
{
if (LogDev->Dma[i].CurrentChannel != 4)
if (LogDev->Dma[i].CurrentChannel != DMACHANNEL_NONE)
ResourceCount++;
else
break;
@ -736,7 +736,7 @@ IsaPnpCreateLogicalDeviceResources(
}
for (i = 0; i < RTL_NUMBER_OF(LogDev->Dma); i++)
{
if (LogDev->Dma[i].CurrentChannel == 4)
if (LogDev->Dma[i].CurrentChannel == DMACHANNEL_NONE)
break;
Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[ResourceCount++];

View file

@ -46,6 +46,7 @@ extern "C" {
#define IRQTYPE_LOW_LEVEL 0x01
#define IRQTYPE_HIGH_EDGE 0x02
#define ISAPNP_DMACHANNEL(n) (0x74 + (n))
#define DMACHANNEL_NONE 4
#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))