From f0e31fe0748e3dd7ae7cfebe863f143f81056298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= Date: Wed, 29 Apr 2015 12:53:41 +0000 Subject: [PATCH] vt_vga: add a timeout while waiting for vertical retrace On one of my systems FreeBSD will fail to boot because vt_vga gets stuck waiting for the vertical retrace if there's no monitor attached. Fix this by adding a timeout and exiting if the vertical retrace times out. Sponsored by: Citrix Systems R&D Reviewed by: emaste, dumbbell Differential Revision: https://reviews.freebsd.org/D2397 --- sys/dev/vt/hw/vga/vt_vga.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/sys/dev/vt/hw/vga/vt_vga.c b/sys/dev/vt/hw/vga/vt_vga.c index e939fdd126f6..689692e27c8c 100644 --- a/sys/dev/vt/hw/vga/vt_vga.c +++ b/sys/dev/vt/hw/vga/vt_vga.c @@ -1035,11 +1035,12 @@ vga_initialize_graphics(struct vt_device *vd) REG_WRITE1(sc, VGA_GC_DATA, 0xff); } -static void +static int vga_initialize(struct vt_device *vd, int textmode) { struct vga_softc *sc = vd->vd_softc; uint8_t x; + int timeout; /* Make sure the VGA adapter is not in monochrome emulation mode. */ x = REG_READ1(sc, VGA_GEN_MISC_OUTPUT_R); @@ -1060,10 +1061,16 @@ vga_initialize(struct vt_device *vd, int textmode) * code therefore also removes that guarantee and appropriate measures * need to be taken. */ + timeout = 10000; do { + DELAY(10); x = REG_READ1(sc, VGA_GEN_INPUT_STAT_1); x &= VGA_GEN_IS1_VR | VGA_GEN_IS1_DE; - } while (x != (VGA_GEN_IS1_VR | VGA_GEN_IS1_DE)); + } while (x != (VGA_GEN_IS1_VR | VGA_GEN_IS1_DE) && --timeout != 0); + if (timeout == 0) { + printf("Timeout initializing vt_vga\n"); + return (ENXIO); + } /* Now, disable the sync. signals. */ REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_MODE_CONTROL); @@ -1194,6 +1201,8 @@ vga_initialize(struct vt_device *vd, int textmode) */ sc->vga_curfg = sc->vga_curbg = 0xff; } + + return (0); } static int @@ -1235,7 +1244,8 @@ vga_init(struct vt_device *vd) vd->vd_width = VT_VGA_WIDTH; vd->vd_height = VT_VGA_HEIGHT; } - vga_initialize(vd, textmode); + if (vga_initialize(vd, textmode) != 0) + return (CN_DEAD); sc->vga_enabled = true; return (CN_INTERNAL);