summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/vga_pci.c71
1 files changed, 54 insertions, 17 deletions
diff --git a/sys/dev/pci/vga_pci.c b/sys/dev/pci/vga_pci.c
index d7ff20f..c64037f 100644
--- a/sys/dev/pci/vga_pci.c
+++ b/sys/dev/pci/vga_pci.c
@@ -81,16 +81,58 @@ SYSCTL_INT(_hw_pci, OID_AUTO, default_vgapci_unit, CTLFLAG_RDTUN,
int
vga_pci_is_boot_display(device_t dev)
{
+ int unit;
+ device_t pcib;
+ uint16_t config;
+
+ /* Check that the given device is a video card */
+ if ((pci_get_class(dev) != PCIC_DISPLAY &&
+ (pci_get_class(dev) != PCIC_OLD ||
+ pci_get_subclass(dev) != PCIS_OLD_VGA)))
+ return (0);
+
+ unit = device_get_unit(dev);
+
+ if (vga_pci_default_unit >= 0) {
+ /*
+ * The boot display device was determined by a previous
+ * call to this function, or the user forced it using
+ * the hw.pci.default_vgapci_unit tunable.
+ */
+ return (vga_pci_default_unit == unit);
+ }
/*
- * Return true if the given device is the default display used
- * at boot time.
+ * The primary video card used as a boot display must have the
+ * "I/O" and "Memory Address Space Decoding" bits set in its
+ * Command register.
+ *
+ * Furthermore, if the card is attached to a bridge, instead of
+ * the root PCI bus, the bridge must have the "VGA Enable" bit
+ * set in its Control register.
*/
- return (
- (pci_get_class(dev) == PCIC_DISPLAY ||
- (pci_get_class(dev) == PCIC_OLD &&
- pci_get_subclass(dev) == PCIS_OLD_VGA)) &&
- device_get_unit(dev) == vga_pci_default_unit);
+
+ pcib = device_get_parent(device_get_parent(dev));
+ if (device_get_devclass(device_get_parent(pcib)) ==
+ devclass_find("pci")) {
+ /*
+ * The parent bridge is a PCI-to-PCI bridge: check the
+ * value of the "VGA Enable" bit.
+ */
+ config = pci_read_config(pcib, PCIR_BRIDGECTL_1, 2);
+ if ((config & PCIB_BCR_VGA_ENABLE) == 0)
+ return (0);
+ }
+
+ config = pci_read_config(dev, PCIR_COMMAND, 2);
+ if ((config & (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN)) == 0)
+ return (0);
+
+ /* This video card is the boot display: record its unit number. */
+ vga_pci_default_unit = unit;
+ device_set_flags(dev, 1);
+
+ return (1);
}
void *
@@ -159,9 +201,6 @@ vga_pci_unmap_bios(device_t dev, void *bios)
static int
vga_pci_probe(device_t dev)
{
- device_t bdev;
- int unit;
- uint16_t bctl;
switch (pci_get_class(dev)) {
case PCIC_DISPLAY:
@@ -175,13 +214,7 @@ vga_pci_probe(device_t dev)
}
/* Probe default display. */
- unit = device_get_unit(dev);
- bdev = device_get_parent(device_get_parent(dev));
- bctl = pci_read_config(bdev, PCIR_BRIDGECTL_1, 2);
- if (vga_pci_default_unit < 0 && (bctl & PCIB_BCR_VGA_ENABLE) != 0)
- vga_pci_default_unit = unit;
- if (vga_pci_default_unit == unit)
- device_set_flags(dev, 1);
+ vga_pci_is_boot_display(dev);
device_set_desc(dev, "VGA-compatible display");
return (BUS_PROBE_GENERIC);
@@ -197,6 +230,10 @@ vga_pci_attach(device_t dev)
device_add_child(dev, "drm", -1);
device_add_child(dev, "drmn", -1);
bus_generic_attach(dev);
+
+ if (vga_pci_is_boot_display(dev))
+ device_printf(dev, "Boot video device\n");
+
return (0);
}
OpenPOWER on IntegriCloud