summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2015-10-30 11:21:02 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2015-10-30 11:21:02 +0000
commit4349f443d21b2ef4bab32588bf193e260bfadd26 (patch)
treee3ccef881757501a38250ce825dddf9d4754a85f
parent7679e2512e2fbc9973bcb0e662e6a9c0ba232f57 (diff)
Fix interaction between inteldrm(4) and efifb(4). If we were booted by UEFI
firmware and the efifb(4) framebuffer address matches one of the BARs associated with the inteldrm(4) device, make inteldrm(4) the console and prevent efifb(4) from attaching. Make sure that we do a full clear of the framebuffer when inteldrm(4) attaches to prevent the contents of the old framebuffer from showing up. Based on an earlier diff from yasuoka@ ok yasuoka@
-rw-r--r--sys/arch/amd64/amd64/efifb.c42
-rw-r--r--sys/arch/amd64/include/efifbvar.h6
-rw-r--r--sys/dev/pci/drm/i915/i915_drv.c40
3 files changed, 74 insertions, 14 deletions
diff --git a/sys/arch/amd64/amd64/efifb.c b/sys/arch/amd64/amd64/efifb.c
index 4f3375f077a..479f89951dd 100644
--- a/sys/arch/amd64/amd64/efifb.c
+++ b/sys/arch/amd64/amd64/efifb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: efifb.c,v 1.6 2015/09/07 18:19:58 kettenis Exp $ */
+/* $OpenBSD: efifb.c,v 1.7 2015/10/30 11:21:01 kettenis Exp $ */
/*
* Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net>
@@ -25,6 +25,7 @@
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/rasops/rasops.h>
+#include <dev/pci/pcivar.h>
#include <machine/biosvar.h>
#include <machine/efifbvar.h>
@@ -93,7 +94,7 @@ efifb_match(struct device *parent, void *cf, void *aux)
struct efifb_attach_args *eaa = aux;
if (strcmp(eaa->eaa_name, efifb_cd.cd_name) == 0 &&
- bios_efiinfo != NULL)
+ efifb_console.paddr != 0)
return (1);
return (0);
@@ -312,3 +313,40 @@ efifb_cnattach(void)
return (0);
}
+
+int
+efifb_is_console(struct pci_attach_args *pa)
+{
+ pci_chipset_tag_t pc = pa->pa_pc;
+ pcitag_t tag = pa->pa_tag;
+ pcireg_t type;
+ bus_addr_t base;
+ bus_size_t size;
+ int reg;
+
+ for (reg = PCI_MAPREG_START; reg < PCI_MAPREG_END; reg += 4) {
+ if (!pci_mapreg_probe(pc, tag, reg, &type))
+ continue;
+
+ if (type == PCI_MAPREG_TYPE_IO)
+ continue;
+
+ if (pci_mapreg_info(pc, tag, reg, type, &base, &size, NULL))
+ continue;
+
+ if (efifb_console.paddr >= base &&
+ efifb_console.paddr < base + size)
+ return 1;
+
+ if (type & PCI_MAPREG_MEM_TYPE_64BIT)
+ reg += 4;
+ }
+
+ return 0;
+}
+
+void
+efifb_cndetach(void)
+{
+ efifb_console.paddr = 0;
+}
diff --git a/sys/arch/amd64/include/efifbvar.h b/sys/arch/amd64/include/efifbvar.h
index bf5668c9a0d..67bfdb33ecd 100644
--- a/sys/arch/amd64/include/efifbvar.h
+++ b/sys/arch/amd64/include/efifbvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: efifbvar.h,v 1.2 2015/08/31 19:56:32 kettenis Exp $ */
+/* $OpenBSD: efifbvar.h,v 1.3 2015/10/30 11:21:01 kettenis Exp $ */
/*
* Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net>
@@ -23,6 +23,10 @@ struct efifb_attach_args {
const char *eaa_name;
};
+struct pci_attach_args;
+
int efifb_cnattach(void);
+int efifb_is_console(struct pci_attach_args *);
+void efifb_cndetach(void);
#endif /* _MACHINE_EFIFB_H_ */
diff --git a/sys/dev/pci/drm/i915/i915_drv.c b/sys/dev/pci/drm/i915/i915_drv.c
index 52a987276c1..7b5b6393284 100644
--- a/sys/dev/pci/drm/i915/i915_drv.c
+++ b/sys/dev/pci/drm/i915/i915_drv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: i915_drv.c,v 1.95 2015/10/29 07:47:03 kettenis Exp $ */
+/* $OpenBSD: i915_drv.c,v 1.96 2015/10/30 11:21:01 kettenis Exp $ */
/*
* Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org>
*
@@ -956,6 +956,14 @@ int i915_reset(struct drm_device *dev)
return 0;
}
+#ifdef __amd64__
+#include "efifb.h"
+#endif
+
+#if NEFIFB > 0
+#include <machine/efifbvar.h>
+#endif
+
#include "intagp.h"
#if NINTAGP > 0
@@ -1223,15 +1231,6 @@ inteldrm_attach(struct device *parent, struct device *self, void *aux)
int console = 0;
int i;
- if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
- PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA &&
- (pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG)
- & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE))
- == (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) {
- console = 1;
- vga_console_attached = 1;
- }
-
info = i915_get_device_id(PCI_PRODUCT(pa->pa_id));
KASSERT(info->gen != 0);
@@ -1244,6 +1243,20 @@ inteldrm_attach(struct device *parent, struct device *self, void *aux)
dev_priv->memex = pa->pa_memex;
dev_priv->regs = &dev_priv->bar;
+ if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
+ PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA &&
+ (pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG)
+ & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE))
+ == (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) {
+ vga_console_attached = 1;
+ console = 1;
+ }
+
+#if NEFIFB > 0
+ if (efifb_is_console(pa))
+ console = 1;
+#endif
+
printf("\n");
inteldrm_driver.num_ioctls = i915_max_ioctl;
@@ -1495,12 +1508,17 @@ inteldrm_attach(struct device *parent, struct device *self, void *aux)
if (ri->ri_bits == NULL)
return;
+#if NEFIFB > 0
+ if (efifb_is_console(pa))
+ efifb_cndetach();
+#endif
+
printf("%s: %dx%d\n", dev_priv->sc_dev.dv_xname,
ri->ri_width, ri->ri_height);
intel_fbdev_restore_mode(dev);
- ri->ri_flg = RI_CENTER | RI_WRONLY | RI_VCONS;
+ ri->ri_flg = RI_CENTER | RI_WRONLY | RI_VCONS | RI_CLEAR;
ri->ri_hw = dev_priv;
rasops_init(ri, 160, 160);