acpi, vga: say what the first real boot actually found
"acpi: 0 PCI interrupts routed through _PRT" on an AMD board meant that every PCIe bridge's devices are wired to the second I/O APIC, which is not driven. It says so now, and that those devices need MSI. "vga: framebuffer disagreement" on an NVIDIA card compared the GOP's framebuffer against BAR0, a 16 MB register block big enough to pass for a screen. The BAR that contains the framebuffer is preferred now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
parent
27bf91cfe0
commit
416aa52b09
2 changed files with 20 additions and 4 deletions
|
|
@ -284,7 +284,7 @@ void
|
||||||
acpi_pci_route(void)
|
acpi_pci_route(void)
|
||||||
{
|
{
|
||||||
uacpi_pci_routing_table *roottab;
|
uacpi_pci_routing_table *roottab;
|
||||||
int i, routed = 0;
|
int i, routed = 0, beyond = 0;
|
||||||
|
|
||||||
if (!ready)
|
if (!ready)
|
||||||
return;
|
return;
|
||||||
|
|
@ -316,8 +316,11 @@ acpi_pci_route(void)
|
||||||
if (gsi < 0)
|
if (gsi < 0)
|
||||||
continue;
|
continue;
|
||||||
if (gsi >= NIRQ_IOAPIC) {
|
if (gsi >= NIRQ_IOAPIC) {
|
||||||
// A second I/O APIC's input. Not reachable here; MSI still is.
|
// A second I/O APIC's input. Not reachable here; MSI still is. AMD
|
||||||
|
// boards wire every PCIe bridge's devices to the GNB's I/O APIC, so
|
||||||
|
// on those this is most of the machine.
|
||||||
d->irq = 0xFF;
|
d->irq = 0xFF;
|
||||||
|
beyond++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (gsi != d->irq)
|
if (gsi != d->irq)
|
||||||
|
|
@ -331,4 +334,7 @@ acpi_pci_route(void)
|
||||||
uacpi_free_pci_routing_table(roottab);
|
uacpi_free_pci_routing_table(roottab);
|
||||||
kinfo("acpi: %d PCI interrupt%s routed through _PRT\n", routed,
|
kinfo("acpi: %d PCI interrupt%s routed through _PRT\n", routed,
|
||||||
routed == 1 ? "" : "s");
|
routed == 1 ? "" : "s");
|
||||||
|
if (beyond)
|
||||||
|
kinfo("acpi: %d more on a second I/O APIC, which is not driven; "
|
||||||
|
"those devices need MSI\n", beyond);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,21 @@
|
||||||
// Display controllers commonly expose two apertures -- the framebuffer and a
|
// Display controllers commonly expose two apertures -- the framebuffer and a
|
||||||
// much smaller register block -- and which index they land on varies, so the
|
// much smaller register block -- and which index they land on varies, so the
|
||||||
// choice is made by size rather than by position.
|
// choice is made by size rather than by position.
|
||||||
|
//
|
||||||
|
// Except that the one the loader's mode actually lives in wins outright. An
|
||||||
|
// NVIDIA card's BAR0 is a 16 MB register block, which is big enough to pass
|
||||||
|
// for an 800x600 framebuffer and is not one; the screen is in BAR1. Taking
|
||||||
|
// the first that fits reported a "disagreement" that was the driver's own.
|
||||||
static struct pci_bar *
|
static struct pci_bar *
|
||||||
framebuffer_bar(struct pci_dev *d)
|
framebuffer_bar(struct pci_dev *d)
|
||||||
{
|
{
|
||||||
uint64 need = vga_fb_size();
|
uint64 need = vga_fb_size(), vbe = vga_fb_phys();
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
struct pci_bar *b = &d->bar[i];
|
||||||
|
if (b->base && !b->is_io && vbe >= b->base && vbe < b->base + b->size)
|
||||||
|
return b;
|
||||||
|
}
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
struct pci_bar *b = &d->bar[i];
|
struct pci_bar *b = &d->bar[i];
|
||||||
if (b->base == 0 || b->is_io)
|
if (b->base == 0 || b->is_io)
|
||||||
|
|
@ -64,7 +74,7 @@ vga_pci_probe(struct pci_dev *d)
|
||||||
return 0; // still ours; nothing more to do
|
return 0; // still ours; nothing more to do
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vbe != 0 && bar->base != vbe) {
|
if (vbe != 0 && (vbe < bar->base || vbe >= bar->base + bar->size)) {
|
||||||
// Trust VBE: it describes the mode that is actually programmed and being
|
// Trust VBE: it describes the mode that is actually programmed and being
|
||||||
// displayed, which is the thing vga.c is writing into. The BAR is the
|
// displayed, which is the thing vga.c is writing into. The BAR is the
|
||||||
// card's whole aperture and the mode may sit at an offset within it. Say
|
// card's whole aperture and the mode may sit at an offset within it. Say
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue