summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorJason Wright <jason@cvs.openbsd.org>2002-03-27 01:15:13 +0000
committerJason Wright <jason@cvs.openbsd.org>2002-03-27 01:15:13 +0000
commit3666c06ca267606a11141438c8eb67a444502809 (patch)
treefb01a5564b21ed8acd428d1be25cc420f04158d1 /sys/arch
parent1b6dda9fdf87f720945ceaaf8d294ad089bb0639 (diff)
Make a shadow copy of the bios rom (if available) and make it available via mmap
Also, don't hardcode the length of the pixel memory in vgafb_mmap(), use the size provided by pci_mem_find.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/sparc64/dev/vgafb.c106
1 files changed, 102 insertions, 4 deletions
diff --git a/sys/arch/sparc64/dev/vgafb.c b/sys/arch/sparc64/dev/vgafb.c
index 36f1ae71424..a76bba5cb03 100644
--- a/sys/arch/sparc64/dev/vgafb.c
+++ b/sys/arch/sparc64/dev/vgafb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vgafb.c,v 1.9 2002/03/27 01:00:48 jason Exp $ */
+/* $OpenBSD: vgafb.c,v 1.10 2002/03/27 01:15:12 jason Exp $ */
/*
* Copyright (c) 2001 Jason L. Wright (jason@thought.net)
@@ -62,8 +62,10 @@ struct vgafb_softc {
bus_space_tag_t sc_mem_t;
bus_space_tag_t sc_io_t;
bus_space_handle_t sc_mem_h, sc_io_h, sc_mmio_h;
- bus_addr_t sc_io_addr, sc_mem_addr, sc_mmio_addr;
- bus_size_t sc_io_size, sc_mem_size, sc_mmio_size;
+ bus_addr_t sc_io_addr, sc_mem_addr, sc_mmio_addr, sc_rom_addr;
+ bus_size_t sc_io_size, sc_mem_size, sc_mmio_size, sc_rom_size;
+ u_int32_t *sc_rom_ptr;
+ int sc_has_rom;
struct rcons sc_rcons;
struct raster sc_raster;
int sc_console;
@@ -101,6 +103,7 @@ struct wsscreen_list vgafb_screenlist = {
};
int vgafb_mapregs(struct vgafb_softc *, struct pci_attach_args *);
+int vgafb_rommap(struct vgafb_softc *, struct pci_attach_args *);
int vgafb_ioctl(void *, u_long, caddr_t, int, struct proc *);
int vgafb_alloc_screen(void *, const struct wsscreen_descr *, void **,
int *, int *, long *);
@@ -407,15 +410,27 @@ vgafb_mmap(v, off, prot)
int prot;
{
struct vgafb_softc *sc = v;
+ paddr_t pa;
+ vaddr_t va;
if (off & PGOFSET)
return (-1);
- if (off >= 0 && off < 0x800000) {
+ if (off >= 0 && off < sc->sc_mem_size) {
return (bus_space_mmap(sc->sc_mem_t, sc->sc_mem_addr, off, prot,
BUS_SPACE_MAP_LINEAR));
}
+ if (sc->sc_rom_ptr != NULL &&
+ off >= sc->sc_rom_addr &&
+ off < sc->sc_rom_addr + sc->sc_rom_size) {
+ off -= sc->sc_rom_addr;
+ va = ((vaddr_t)sc->sc_rom_ptr) + off;
+ if (pmap_extract(pmap_kernel(), va, &pa) == FALSE)
+ return (-1);
+ return (pa);
+ }
+
return (-1);
}
@@ -440,6 +455,87 @@ vgafb_is_console(node)
return (fbnode == node);
}
+#define PCI_ROMBAR_REG 0x30
+#define PCI_ROMBAR_ADDR(mr) \
+ ((mr) & PCI_ROMBAR_ADDR_MASK)
+#define PCI_ROMBAR_SIZE(mr) \
+ (PCI_ROMBAR_ADDR(mr) & -PCI_ROMBAR_ADDR(mr))
+#define PCI_ROMBAR_ADDR_ENABLE 0x00000001
+#define PCI_ROMBAR_ADDR_MASK 0xfffff800
+
+/* offsets into the rom space */
+#define PCI_ROM_OFF_MAGIC0 0x0
+#define PCI_ROM_OFF_MAGIC1 0x1
+
+/* rom header magic numbers */
+#define PCI_ROM_MAGIC0 0x55
+#define PCI_ROM_MAGIC1 0xaa
+
+int
+vgafb_rommap(sc, pa)
+ struct vgafb_softc *sc;
+ struct pci_attach_args *pa;
+{
+ bus_space_handle_t bh;
+ u_int32_t origaddr, address, mask, size, *romptr, *p, i;
+ int s;
+
+ s = splhigh();
+ origaddr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROMBAR_REG);
+ pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROMBAR_REG,
+ PCI_ROMBAR_ADDR_MASK);
+ mask = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROMBAR_REG);
+ pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROMBAR_REG, origaddr);
+ address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROMBAR_REG);
+ splx(s);
+
+ /* No ROM supported? */
+ if (mask == 0)
+ return (0);
+
+ address &= PCI_ROMBAR_ADDR_MASK;
+
+ /* Turn on the address decoder please... */
+ pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROMBAR_REG,
+ address | PCI_ROMBAR_ADDR_ENABLE);
+
+ size = PCI_ROMBAR_SIZE(mask);
+
+ if (bus_space_map2(pa->pa_memt, SBUS_BUS_SPACE, address, size, 0,
+ NULL, &bh)) {
+ pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROMBAR_REG, origaddr);
+ return (0);
+ }
+
+ if ((bus_space_read_1(pa->pa_memt, bh, PCI_ROM_OFF_MAGIC0) !=
+ PCI_ROM_MAGIC0) ||
+ (bus_space_read_1(pa->pa_memt, bh, PCI_ROM_OFF_MAGIC1) !=
+ PCI_ROM_MAGIC1)) {
+ /* ROM is supported but not present */
+ bus_space_unmap(pa->pa_memt, bh, size);
+ pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROMBAR_REG, origaddr);
+ return (0);
+ }
+
+ romptr = (u_int32_t *)malloc(size, M_DEVBUF, M_NOWAIT);
+ if (romptr == NULL) {
+ bus_space_unmap(pa->pa_memt, bh, size);
+ pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROMBAR_REG, origaddr);
+ return (0);
+ }
+
+ for (p = romptr, i = 0; i < size; i += 4, p++)
+ *p = bus_space_read_4(pa->pa_memt, bh, i);
+
+ sc->sc_rom_ptr = romptr;
+ sc->sc_rom_addr = address;
+ sc->sc_rom_size = size;
+
+ bus_space_unmap(pa->pa_memt, bh, size);
+ pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROMBAR_REG, origaddr);
+ return (0);
+}
+
int
vgafb_mapregs(sc, pa)
struct vgafb_softc *sc;
@@ -450,6 +546,8 @@ vgafb_mapregs(sc, pa)
int hasio = 0, hasmem = 0, hasmmio = 0;
u_int32_t i, cf;
+ vgafb_rommap(sc, pa);
+
for (i = 0x10; i <= 0x18; i += 4) {
cf = pci_conf_read(pa->pa_pc, pa->pa_tag, i);
if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO) {