diff options
author | Jason Wright <jason@cvs.openbsd.org> | 2002-03-27 01:15:13 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 2002-03-27 01:15:13 +0000 |
commit | 3666c06ca267606a11141438c8eb67a444502809 (patch) | |
tree | fb01a5564b21ed8acd428d1be25cc420f04158d1 /sys/arch | |
parent | 1b6dda9fdf87f720945ceaaf8d294ad089bb0639 (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.c | 106 |
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) { |