Skip to content

Commit 1466cee

Browse files
committed
Legacy IRQ Support
1 parent 021d038 commit 1466cee

16 files changed

Lines changed: 802 additions & 117 deletions

File tree

drivers/bus/pcix/arb/ar_memio.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ ario_Constructor(IN PVOID DeviceExtension,
175175
UNREFERENCED_PARAMETER(Version);
176176
UNREFERENCED_PARAMETER(Size);
177177
UNREFERENCED_PARAMETER(Interface);
178+
UNREFERENCED_PARAMETER(FdoExtension);
178179

179180
/* Make sure it's the expected interface */
180181
if ((ULONG_PTR)InterfaceData == CmResourceTypePort)
@@ -281,6 +282,7 @@ armem_Constructor(IN PVOID DeviceExtension,
281282
UNREFERENCED_PARAMETER(Version);
282283
UNREFERENCED_PARAMETER(Size);
283284
UNREFERENCED_PARAMETER(Interface);
285+
UNREFERENCED_PARAMETER(FdoExtension);
284286

285287
/* Make sure it's the expected interface */
286288
if ((ULONG_PTR)InterfaceData == CmResourceTypeMemory)

drivers/bus/pcix/arb/arb_comn.c

Lines changed: 172 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
/* GLOBALS ********************************************************************/
1818

19-
PUCHAR PciArbiterNames[] =
19+
PCHAR PciArbiterNames[] =
2020
{
2121
"I/O Port",
2222
"Memory",
@@ -107,6 +107,22 @@ PciArbBuildAndCommitFromRequirements(
107107
if (!TargetArb) continue;
108108
AInst = &TargetArb->CommonInstance;
109109

110+
/*
111+
* Make sure the arbiter we looked up actually arbitrates this resource
112+
* type. If the secondary-extension list is mis-wired (e.g. the memory
113+
* slot resolving to the bus-number arbiter), feeding it the wrong
114+
* descriptor type would make PackResource fail and the arbiter library
115+
* assert. Skip rather than crash; the kernel root arbiters still
116+
* perform the real assignment.
117+
*/
118+
if (AInst->ResourceType != Type)
119+
{
120+
DPRINT1("PCI: %s arbiter has mismatched ResourceType %u (expected %u), skipping\n",
121+
(Type == CmResourceTypePort) ? "I/O" : "Memory",
122+
AInst->ResourceType, Type);
123+
continue;
124+
}
125+
110126
/* Count how many alternative lists provide a descriptor of same type at this index */
111127
for (iAlt = 0; iAlt < AltCount; iAlt++)
112128
{
@@ -162,6 +178,25 @@ PciArbBuildAndCommitFromRequirements(
162178
ArbEntry->BusNumber = ReqList->BusNumber;
163179
ArbEntry->Result = ArbiterResultUndefined;
164180

181+
/*
182+
* The arbiter library packs the granted resource into Entry->Assignment
183+
* (via PackResource) but does not allocate that buffer itself - the
184+
* caller must provide it. Without this, PackResource receives a NULL
185+
* descriptor, returns STATUS_INVALID_PARAMETER, and ArbAllocateEntry
186+
* asserts.
187+
*/
188+
ArbEntry->Assignment = ExAllocatePoolWithTag(PagedPool,
189+
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),
190+
PCI_POOL_TAG);
191+
if (!ArbEntry->Assignment)
192+
{
193+
RemoveEntryList(&ArbEntry->ListEntry);
194+
ExFreePoolWithTag(ArbEntry, PCI_POOL_TAG);
195+
ExFreePoolWithTag(AltBuffer, PCI_POOL_TAG);
196+
continue;
197+
}
198+
RtlZeroMemory(ArbEntry->Assignment, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
199+
165200
if (AInst->TestAllocation)
166201
{
167202
NTSTATUS St = AInst->TestAllocation(AInst, &ArbHead);
@@ -178,6 +213,7 @@ PciArbBuildAndCommitFromRequirements(
178213

179214
/* Free temp structures; arbiter copied selected ranges internally */
180215
RemoveEntryList(&ArbEntry->ListEntry);
216+
ExFreePoolWithTag(ArbEntry->Assignment, PCI_POOL_TAG);
181217
ExFreePoolWithTag(ArbEntry, PCI_POOL_TAG);
182218
ExFreePoolWithTag(AltBuffer, PCI_POOL_TAG);
183219
}
@@ -231,7 +267,10 @@ PciInitializeArbiters(IN PPCI_FDO_EXTENSION FdoExtension)
231267
PPCI_INTERFACE CurrentInterface, *Interfaces;
232268
PPCI_PDO_EXTENSION PdoExtension;
233269
PPCI_ARBITER_INSTANCE ArbiterInterface;
234-
NTSTATUS Status;
270+
/* Default to success: a subtractive-decode bridge (or a bus with no
271+
matching arbiter interfaces) creates no arbiters and skips every loop
272+
iteration, leaving Status otherwise unassigned. */
273+
NTSTATUS Status = STATUS_SUCCESS;
235274
PCI_SIGNATURE ArbiterType;
236275
ASSERT_FDO(FdoExtension);
237276

@@ -319,6 +358,82 @@ PciInitializeArbiters(IN PPCI_FDO_EXTENSION FdoExtension)
319358
return Status;
320359
}
321360

361+
/*
362+
* A single decode window [Base, End] of a PCI-PCI bridge, used to confine the
363+
* bridge's per-bus arbiters to the aperture (sub-arbitration).
364+
*/
365+
typedef struct _PCI_ARB_WINDOW
366+
{
367+
ULONGLONG Base;
368+
ULONGLONG End;
369+
} PCI_ARB_WINDOW;
370+
371+
/* Sort up to a handful of windows ascending by base (simple, n is tiny) */
372+
static
373+
VOID
374+
PciSortArbWindows(IN OUT PCI_ARB_WINDOW *Windows, IN ULONG Count)
375+
{
376+
ULONG i, j;
377+
for (i = 0; (i + 1) < Count; i++)
378+
{
379+
for (j = 0; (j + 1) < (Count - i); j++)
380+
{
381+
if (Windows[j].Base > Windows[j + 1].Base)
382+
{
383+
PCI_ARB_WINDOW Tmp = Windows[j];
384+
Windows[j] = Windows[j + 1];
385+
Windows[j + 1] = Tmp;
386+
}
387+
}
388+
}
389+
}
390+
391+
/*
392+
* Reserve everything OUTSIDE the given (sorted, ascending) decode windows in a
393+
* bridge's per-bus arbiter, so child devices can only be allocated within the
394+
* bridge aperture. Reserving the complement (rather than the windows) keeps the
395+
* in-window child addresses free, so BIOS-assigned children are unaffected.
396+
*/
397+
static
398+
VOID
399+
PciSeedBridgeArbiterComplement(IN PARBITER_INSTANCE Arb,
400+
IN PCI_ARB_WINDOW *Windows,
401+
IN ULONG Count,
402+
IN ULONGLONG SpaceMax)
403+
{
404+
ULONGLONG Cursor = 0;
405+
ULONG i;
406+
407+
if (!Arb || !Arb->Allocation || (Count == 0)) return;
408+
409+
for (i = 0; i < Count; i++)
410+
{
411+
ULONGLONG Base = Windows[i].Base;
412+
ULONGLONG End = Windows[i].End;
413+
414+
/* Ignore windows that fall outside the space this arbiter manages */
415+
if (Base > SpaceMax) break;
416+
417+
/* Reserve the gap below this window */
418+
if (Base > Cursor)
419+
{
420+
(VOID)RtlAddRange(Arb->Allocation, Cursor, Base - 1, 0,
421+
RTL_RANGE_LIST_ADD_IF_CONFLICT, NULL, NULL);
422+
}
423+
424+
/* The window itself stays free; advance past it (handles overlap) */
425+
if (End >= SpaceMax) return;
426+
if ((End + 1) > Cursor) Cursor = End + 1;
427+
}
428+
429+
/* Reserve everything above the last window */
430+
if (Cursor <= SpaceMax)
431+
{
432+
(VOID)RtlAddRange(Arb->Allocation, Cursor, SpaceMax, 0,
433+
RTL_RANGE_LIST_ADD_IF_CONFLICT, NULL, NULL);
434+
}
435+
}
436+
322437
NTSTATUS
323438
NTAPI
324439
PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension,
@@ -328,8 +443,9 @@ PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension,
328443
//CM_RESOURCE_TYPE DesiredType;
329444
PVOID Instance;
330445
PCI_SIGNATURE ArbiterType;
331-
332-
UNREFERENCED_PARAMETER(Resources);
446+
/* Bridge decode windows gathered from the assigned (boot) resources */
447+
PCI_ARB_WINDOW IoWin[4], MemWin[4];
448+
ULONG IoWinCount = 0, MemWinCount = 0;
333449

334450
/* If this is the root and we have boot resources not yet parsed, do a simple parse now.
335451
Later these will be used to add fixed allocations into the arbiter once implemented. */
@@ -403,6 +519,38 @@ PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension,
403519
DPRINT1("PCI Skipping arbiter initialization for subtractive bridge FDOX %p\n", DeviceExtension);
404520
return STATUS_SUCCESS;
405521
}
522+
523+
/* Gather the bridge's decode window(s) from the assigned resources so the
524+
per-bus arbiters below can be confined to the aperture. The assigned
525+
resource list contains the bridge's I/O and memory (and prefetch
526+
memory) windows as Port/Memory partial descriptors. */
527+
if ((Resources) && (Resources->Count))
528+
{
529+
PCM_PARTIAL_RESOURCE_LIST PartialList = &Resources->List[0].PartialResourceList;
530+
PCM_PARTIAL_RESOURCE_DESCRIPTOR Desc = PartialList->PartialDescriptors;
531+
ULONG k;
532+
533+
for (k = 0; k < PartialList->Count; k++, Desc++)
534+
{
535+
if ((Desc->Type == CmResourceTypePort) && (Desc->u.Port.Length) &&
536+
(IoWinCount < RTL_NUMBER_OF(IoWin)))
537+
{
538+
IoWin[IoWinCount].Base = (ULONGLONG)Desc->u.Port.Start.QuadPart;
539+
IoWin[IoWinCount].End = IoWin[IoWinCount].Base + Desc->u.Port.Length - 1;
540+
IoWinCount++;
541+
}
542+
else if ((Desc->Type == CmResourceTypeMemory) && (Desc->u.Memory.Length) &&
543+
(MemWinCount < RTL_NUMBER_OF(MemWin)))
544+
{
545+
MemWin[MemWinCount].Base = (ULONGLONG)Desc->u.Memory.Start.QuadPart;
546+
MemWin[MemWinCount].End = MemWin[MemWinCount].Base + Desc->u.Memory.Length - 1;
547+
MemWinCount++;
548+
}
549+
}
550+
551+
PciSortArbWindows(IoWin, IoWinCount);
552+
PciSortArbWindows(MemWin, MemWinCount);
553+
}
406554
}
407555

408556
/* Loop all arbiters */
@@ -464,6 +612,26 @@ PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension,
464612
if (DeviceExtension->BootRangeSeedMask == 0x3)
465613
DeviceExtension->BootRangesSeeded = TRUE; /* both types seeded */
466614
}
615+
else if (!PCI_IS_ROOT_FDO(DeviceExtension))
616+
{
617+
/* Non-root (PCI-PCI bridge) FDO: confine this arbiter to the
618+
bridge's decode window(s) by reserving everything outside
619+
them. I/O and memory are 32-bit on these bridges. */
620+
PARBITER_INSTANCE Arb = &((PPCI_ARBITER_INSTANCE)Instance)->CommonInstance;
621+
622+
if ((ArbiterType == PciArb_Io) && (IoWinCount))
623+
{
624+
PciSeedBridgeArbiterComplement(Arb, IoWin, IoWinCount, 0xFFFFFFFFULL);
625+
DPRINT1("PCI: bridge FDO %p I/O arbiter confined to %lu window(s)\n",
626+
DeviceExtension, IoWinCount);
627+
}
628+
else if ((ArbiterType == PciArb_Memory) && (MemWinCount))
629+
{
630+
PciSeedBridgeArbiterComplement(Arb, MemWin, MemWinCount, 0xFFFFFFFFULL);
631+
DPRINT1("PCI: bridge FDO %p Memory arbiter confined to %lu window(s)\n",
632+
DeviceExtension, MemWinCount);
633+
}
634+
}
467635
}
468636
else
469637
{

drivers/bus/pcix/arb/tr_irq.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,13 @@ tranirq_Constructor(IN PVOID DeviceExtension,
8181
}
8282
else
8383
{
84-
/* It's not, so we have to get the root bus' bus number instead */
85-
#if 0 // when have PDO commit
86-
ParentBus = FdoExtension->PhysicalDeviceObject->DeviceExtension->ParentFdoExtension->BaseBus;
84+
/* It's not, so the parent is the bridge's PDO sitting on a PCI bus */
85+
PPCI_PDO_EXTENSION BridgePdo =
86+
(PPCI_PDO_EXTENSION)FdoExtension->PhysicalDeviceObject->DeviceExtension;
87+
ParentBus = BridgePdo->ParentFdoExtension->BaseBus;
8788
ParentInterface = PCIBus;
8889
DPRINT1(" Is bridge FDO, parent bus %x, secondary bus %x\n",
8990
ParentBus, BaseBus);
90-
#endif
9191
}
9292

9393
/* Now call the legacy HAL interface to get the correct translator */

drivers/bus/pcix/enum.c

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,24 @@ PciBuildRequirementsList(IN PPCI_PDO_EXTENSION PdoExtension,
496496
}
497497
}
498498

499+
/*
500+
* Add an interrupt requirement when the device has an interrupt pin and the
501+
* routing logic resolved it to a valid legacy PIC IRQ (see
502+
* PciGetAdjustedInterruptLine -> PciRouteInterrupt). This is what lets the
503+
* IRQ actually be arbitrated and translated; previously the interrupt was
504+
* never expressed in the requirements list. The IRQ is presented as a
505+
* fixed value rather than the full $PIR mask because, with the global IRQ
506+
* arbiter, nothing re-programs the router after arbitration - so the IRQ the
507+
* link is physically steered to is the only valid choice.
508+
*/
509+
if ((PdoExtension->InterruptPin) &&
510+
(PdoExtension->AdjustedInterruptLine >= 1) &&
511+
(PdoExtension->AdjustedInterruptLine <= 15))
512+
{
513+
DescriptorCount += 1;
514+
HaveAny = TRUE;
515+
}
516+
499517
if (!HaveAny)
500518
{
501519
/* Use (and cache) the zero list */
@@ -543,6 +561,21 @@ PciBuildRequirementsList(IN PPCI_PDO_EXTENSION PdoExtension,
543561
IoDesc++;
544562
}
545563

564+
/* Emit the routed interrupt requirement (counted above) */
565+
if ((PdoExtension->InterruptPin) &&
566+
(PdoExtension->AdjustedInterruptLine >= 1) &&
567+
(PdoExtension->AdjustedInterruptLine <= 15))
568+
{
569+
RtlZeroMemory(IoDesc, sizeof(*IoDesc));
570+
IoDesc->Option = 0;
571+
IoDesc->Type = CmResourceTypeInterrupt;
572+
IoDesc->ShareDisposition = CmResourceShareShared;
573+
IoDesc->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
574+
IoDesc->u.Interrupt.MinimumVector = PdoExtension->AdjustedInterruptLine;
575+
IoDesc->u.Interrupt.MaximumVector = PdoExtension->AdjustedInterruptLine;
576+
IoDesc++;
577+
}
578+
546579
*Buffer = RequirementsList;
547580
PciDebugPrintIoResReqList(RequirementsList);
548581
return STATUS_SUCCESS;
@@ -1496,20 +1529,27 @@ PciProcessBus(IN PPCI_FDO_EXTENSION DeviceExtension)
14961529
PhysicalDeviceObject = DeviceExtension->PhysicalDeviceObject;
14971530
PdoExtension = (PPCI_PDO_EXTENSION)PhysicalDeviceObject->DeviceExtension;
14981531

1499-
/* Cheeck if this is the root bus */
1532+
/*
1533+
* This is a post-enumeration pass that would set up legacy VGA/ISA decode
1534+
* forwarding through PCI-PCI bridges. None of it is implemented yet, and
1535+
* none is required to boot: devices already received their resources during
1536+
* enumeration/start. Log what would be done and proceed instead of breaking
1537+
* into the debugger.
1538+
*/
1539+
1540+
/* Check if this is the root bus */
15001541
if (!PCI_IS_ROOT_FDO(DeviceExtension))
15011542
{
1502-
/* Not really handling this year */
1503-
UNIMPLEMENTED_DBGBREAK();
1504-
15051543
/* Check for PCI bridges with the ISA bit set, or required */
15061544
if ((PdoExtension) &&
15071545
(PciClassifyDeviceType(PdoExtension) == PciTypePciBridge) &&
15081546
((PdoExtension->Dependent.type1.IsaBitRequired) ||
15091547
(PdoExtension->Dependent.type1.IsaBitSet)))
15101548
{
1511-
/* We'll need to do some legacy support */
1512-
UNIMPLEMENTED_DBGBREAK();
1549+
/* Legacy ISA decode forwarding through this bridge is not implemented;
1550+
the bridge still functions, only legacy ISA aliasing is skipped. */
1551+
DPRINT1("PCI: bridge FDO %p has ISA decode bit set; legacy ISA "
1552+
"forwarding not implemented (skipped)\n", DeviceExtension);
15131553
}
15141554
}
15151555
else
@@ -1522,17 +1562,21 @@ PciProcessBus(IN PPCI_FDO_EXTENSION DeviceExtension)
15221562
/* Find any that have the VGA decode bit on */
15231563
if (PdoExtension->Dependent.type1.VgaBitSet)
15241564
{
1525-
/* Again, some more legacy support we'll have to do */
1526-
UNIMPLEMENTED_DBGBREAK();
1565+
/* Legacy VGA decode forwarding through this bridge is not
1566+
implemented; VGA on the root bus is unaffected. */
1567+
DPRINT1("PCI: child bridge PDO %p has VGA decode bit set; legacy "
1568+
"VGA forwarding not implemented (skipped)\n", PdoExtension);
15271569
}
15281570
}
15291571
}
15301572

15311573
/* Check for ACPI systems where the OS assigns bus numbers */
15321574
if (PciAssignBusNumbers)
15331575
{
1534-
/* Not yet supported */
1535-
UNIMPLEMENTED_DBGBREAK();
1576+
/* OS-assigned bus numbers are not yet supported; the firmware-assigned
1577+
numbers are used as-is. */
1578+
DPRINT1("PCI: PciAssignBusNumbers set but OS bus-number assignment is "
1579+
"not implemented (using firmware assignment)\n");
15361580
}
15371581
}
15381582

0 commit comments

Comments
 (0)