Subject: VGA_POST patch to replace "vbetool post"
To: None <current-users@netbsd.org>
From: Joerg Sonnenberger <joerg@britannica.bec.de>
List: current-users
Date: 12/21/2007 23:25:34
--JP+T4n/bALQSJXh8
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Hi all,
attached is a patch for x86 to use x86emu to reset vga(4) on resume.
Please test this by adding X86EMU and VGA_POST to your kernel config and
set machdep.acpi_vbios_reset=0. I am interested to hear on which systems
it works and doesn't work. I hope in the long term to replace that
sysctl with the VGA_POST option/code.
http://www.netbsd.org/~joerg/netbsd-amd64-vga_post.bz2 can be used as
well.
Joerg
--JP+T4n/bALQSJXh8
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="vga_post.diff"
Index: dev/pci/files.pci
===================================================================
RCS file: /data/repo/netbsd/src/sys/dev/pci/files.pci,v
retrieving revision 1.299
diff -u -p -r1.299 files.pci
--- dev/pci/files.pci 15 Dec 2007 05:46:21 -0000 1.299
+++ dev/pci/files.pci 18 Dec 2007 14:34:43 -0000
@@ -391,6 +391,7 @@ attach esh at pci with esh_pci
file dev/pci/if_esh_pci.c esh_pci
# generic PCI VGA
+defflag opt_vga.h VGA_POST
attach vga at pci with vga_pci
file dev/pci/vga_pci.c vga_pci needs-flag
Index: dev/pci/vga_pci.c
===================================================================
RCS file: /data/repo/netbsd/src/sys/dev/pci/vga_pci.c,v
retrieving revision 1.37
diff -u -p -r1.37 vga_pci.c
--- dev/pci/vga_pci.c 9 Dec 2007 20:28:13 -0000 1.37
+++ dev/pci/vga_pci.c 21 Dec 2007 19:30:34 -0000
@@ -52,6 +52,12 @@ __KERNEL_RCSID(0, "$NetBSD: vga_pci.c,v
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
+#include "opt_vga.h"
+
+#ifdef VGA_POST
+#include <x86/vga_post.h>
+#endif
+
#define NBARS 6 /* number of PCI BARs */
struct vga_bar {
@@ -70,7 +76,9 @@ struct vga_pci_softc {
struct vga_bar sc_bars[NBARS];
struct vga_bar sc_rom;
- struct pci_conf_state sc_pciconf;
+#ifdef VGA_POST
+ struct vga_post *sc_posth;
+#endif
};
static int vga_pci_match(struct device *, struct cfdata *, void *);
@@ -221,6 +229,12 @@ vga_pci_attach(struct device *parent, st
vga_common_attach(sc, pa->pa_iot, pa->pa_memt, WSDISPLAY_TYPE_PCIVGA,
vga_pci_lookup_quirks(pa), &vga_pci_funcs);
+#ifdef VGA_POST
+ psc->sc_posth = vga_post_init(pa->pa_bus, pa->pa_device, pa->pa_function);
+ if (psc->sc_posth == NULL)
+ aprint_error_dev(self, "WARNING: could not prepare POST handler\n");
+#endif
+
/*
* XXX Do not use the generic PCI framework for now as
* XXX it would power down the device when the console
@@ -238,6 +252,11 @@ vga_pci_resume(device_t dv)
vga_resume(&sc->sc_vga);
+#ifdef VGA_POST
+ if (sc->sc_posth != NULL)
+ vga_post_call(sc->sc_posth);
+#endif
+
return true;
}
Index: arch/x86/conf/files.x86
===================================================================
RCS file: /data/repo/netbsd/src/sys/arch/x86/conf/files.x86,v
retrieving revision 1.37
diff -u -p -r1.37 files.x86
--- arch/x86/conf/files.x86 18 Dec 2007 07:17:16 -0000 1.37
+++ arch/x86/conf/files.x86 18 Dec 2007 14:35:05 -0000
@@ -96,3 +96,5 @@ file arch/x86/x86/coretemp.c intel_core
device ipmi: sysmon_envsys, sysmon_wdog
attach ipmi at ipmibus
file arch/x86/x86/ipmi.c ipmi needs-flag
+
+file arch/x86/x86/vga_post.c vga_post
Index: arch/x86/include/vga_post.h
===================================================================
RCS file: arch/x86/include/vga_post.h
diff -N arch/x86/include/vga_post.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ arch/x86/include/vga_post.h 21 Dec 2007 19:50:42 -0000
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _X86_VGA_POST_H_
+#define _X86_VGA_POST_H_
+
+#ifdef _KERNEL
+struct vga_post;
+
+struct vga_post *vga_post_init(int, int, int);
+void vga_post_free(struct vga_post *);
+void vga_post_call(struct vga_post *);
+#endif
+#endif
Index: arch/x86/x86/vga_post.c
===================================================================
RCS file: arch/x86/x86/vga_post.c
diff -N arch/x86/x86/vga_post.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ arch/x86/x86/vga_post.c 21 Dec 2007 20:11:26 -0000
@@ -0,0 +1,182 @@
+/*-
+ * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/kmem.h>
+#include <uvm/uvm_extern.h>
+#include <uvm/uvm_page.h>
+
+#include <machine/pio.h>
+
+#include <x86/vga_post.h>
+
+#include <x86emu/x86emu.h>
+#include <x86emu/x86emu_i8254.h>
+#include <x86emu/x86emu_regs.h>
+
+struct vga_post {
+ struct X86EMU emu;
+ vaddr_t sys_image;
+ uint32_t initial_eax;
+ struct x86emu_i8254 i8254;
+};
+
+static uint8_t
+vm86_emu_inb(struct X86EMU *emu, uint16_t port)
+{
+ struct vga_post *sc = emu->sys_private;
+
+ if (port == 0xb2) /* APM scratch register */
+ return 0;
+
+ if (port >= 0x80 && port < 0x88) /* POST status register */
+ return 0;
+
+ if (x86emu_i8254_claim_port(&sc->i8254, port) && 0) {
+ return x86emu_i8254_inb(&sc->i8254, port);
+ } else
+ return inb(port);
+}
+
+static uint16_t
+vm86_emu_inw(struct X86EMU *emu, uint16_t port)
+{
+ if (port >= 0x80 && port < 0x88) /* POST status register */
+ return 0;
+
+ return inw(port);
+}
+
+static uint32_t
+vm86_emu_inl(struct X86EMU *emu, uint16_t port)
+{
+ if (port >= 0x80 && port < 0x88) /* POST status register */
+ return 0;
+
+ return inl(port);
+}
+
+static void
+vm86_emu_outb(struct X86EMU *emu, uint16_t port, uint8_t val)
+{
+ struct vga_post *sc = emu->sys_private;
+
+ if (port == 0xb2) /* APM scratch register */
+ return;
+
+ if (port >= 0x80 && port < 0x88) /* POST status register */
+ return;
+
+ if (x86emu_i8254_claim_port(&sc->i8254, port) && 0) {
+ x86emu_i8254_outb(&sc->i8254, port, val);
+ } else
+ outb(port, val);
+}
+
+static void
+vm86_emu_outw(struct X86EMU *emu, uint16_t port, uint16_t val)
+{
+ if (port >= 0x80 && port < 0x88) /* POST status register */
+ return;
+
+ outw(port, val);
+}
+
+static void
+vm86_emu_outl(struct X86EMU *emu, uint16_t port, uint32_t val)
+{
+ if (port >= 0x80 && port < 0x88) /* POST status register */
+ return;
+
+ outl(port, val);
+}
+
+struct vga_post *
+vga_post_init(int bus, int device, int function)
+{
+ struct vga_post *sc;
+ vaddr_t rom;
+ vaddr_t sys_image;
+
+ sys_image = uvm_km_alloc(kernel_map, 1024 * 1024, 0, UVM_KMF_VAONLY);
+ if (sys_image == 0)
+ return NULL;
+ sc = kmem_alloc(sizeof(*sc), KM_SLEEP);
+
+ sc->sys_image = sys_image;
+ sc->emu.sys_private = sc;
+
+ pmap_kenter_pa(sc->sys_image, 0, VM_PROT_READ | VM_PROT_WRITE);
+ for (rom = 640 * 1024; rom < 1024 * 1024; rom += 4096)
+ pmap_kenter_pa(sc->sys_image + rom, rom, VM_PROT_READ | VM_PROT_WRITE);
+ pmap_update(pmap_kernel());
+
+ memset(&sc->emu, 0, sizeof(sc->emu));
+ X86EMU_init_default(&sc->emu);
+ sc->emu.emu_inb = vm86_emu_inb;
+ sc->emu.emu_inw = vm86_emu_inw;
+ sc->emu.emu_inl = vm86_emu_inl;
+ sc->emu.emu_outb = vm86_emu_outb;
+ sc->emu.emu_outw = vm86_emu_outw;
+ sc->emu.emu_outl = vm86_emu_outl;
+
+ sc->emu.mem_base = (char *)sc->sys_image;
+ sc->emu.mem_size = 1024 * 1024;
+
+ sc->initial_eax = bus * 256 + device * 8 + function;
+
+ return sc;
+}
+
+void
+vga_post_call(struct vga_post *sc)
+{
+ sc->emu.x86.R_EAX = sc->initial_eax;
+ sc->emu.x86.R_EDX = 0x00000080;
+ sc->emu.x86.R_DS = 0x0040;
+ sc->emu.x86.register_flags = 0x3200;
+
+ /* stack is at the end of the first 4KB */
+ sc->emu.x86.R_SS = 0;
+ sc->emu.x86.R_ESP = 4096;
+
+ x86emu_i8254_init(&sc->i8254, nanotime);
+
+ /* Jump straight into the VGA BIOS POST code */
+ X86EMU_exec_call(&sc->emu, 0xc000, 0x0003);
+}
+
+void
+vga_post_free(struct vga_post *sc)
+{
+ pmap_kremove(sc->sys_image, 1024 * 1024);
+ pmap_update(pmap_kernel());
+ kmem_free(sc, sizeof(*sc));
+}
--JP+T4n/bALQSJXh8--