From 5220019c041923e91490ddda3f780a5cf9fdb5b8 Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Thu, 26 Sep 2013 22:47:02 +0000 Subject: Allow Open Firmware syscons to attach to devices without an "address" property such as those found on some real and emulated IBM systems. The approach, which is taken from Linux, is to scan through the PCI bars until we find one large enough to contain the linear framebuffer and which is ideally prefetchable if no "address" property can be found. This makes the graphical console work with the pSeries target in QEMU. Approved by: re (delphij) --- sys/powerpc/ofw/ofw_machdep.c | 6 ++- sys/powerpc/ofw/ofw_syscons.c | 97 ++++++++++++++++++++++++++++++------------- sys/powerpc/ofw/ofw_syscons.h | 1 + 3 files changed, 74 insertions(+), 30 deletions(-) (limited to 'sys/powerpc') diff --git a/sys/powerpc/ofw/ofw_machdep.c b/sys/powerpc/ofw/ofw_machdep.c index 448393d..24aa24e 100644 --- a/sys/powerpc/ofw/ofw_machdep.c +++ b/sys/powerpc/ofw/ofw_machdep.c @@ -680,7 +680,7 @@ OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag, bus_size_t size, rsize; uint32_t c, nbridge, naddr, nsize; phandle_t bridge, parent; - u_int spc, rspc; + u_int spc, rspc, prefetch; int pci, pcib, res; /* Sanity checking. */ @@ -707,6 +707,7 @@ OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag, if (regno + naddr + nsize > res) return (EINVAL); spc = (pci) ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK : ~0; + prefetch = (pci) ? cell[regno] & OFW_PCI_PHYS_HI_PREFETCHABLE : 0; addr = 0; for (c = 0; c < naddr; c++) addr = ((uint64_t)addr << 32) | cell[regno++]; @@ -763,6 +764,7 @@ OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag, } *tag = &bs_le_tag; - return (bus_space_map(*tag, addr, size, 0, handle)); + return (bus_space_map(*tag, addr, size, + prefetch ? BUS_SPACE_MAP_PREFETCHABLE : 0, handle)); } diff --git a/sys/powerpc/ofw/ofw_syscons.c b/sys/powerpc/ofw/ofw_syscons.c index 1c1c4c1..bee9672 100644 --- a/sys/powerpc/ofw/ofw_syscons.c +++ b/sys/powerpc/ofw/ofw_syscons.c @@ -199,13 +199,18 @@ ofwfb_foreground(uint8_t attr) } static u_int -ofwfb_pix32(int attr) +ofwfb_pix32(struct ofwfb_softc *sc, int attr) { u_int retval; - retval = (ofwfb_cmap[attr].blue << 16) | - (ofwfb_cmap[attr].green << 8) | - ofwfb_cmap[attr].red; + if (sc->sc_tag == &bs_le_tag) + retval = (ofwfb_cmap[attr].red << 16) | + (ofwfb_cmap[attr].green << 8) | + ofwfb_cmap[attr].blue; + else + retval = (ofwfb_cmap[attr].blue << 16) | + (ofwfb_cmap[attr].green << 8) | + ofwfb_cmap[attr].red; return (retval); } @@ -221,6 +226,7 @@ ofwfb_configure(int flags) int depth; int disable; int len; + int i; char type[16]; static int done = 0; @@ -265,7 +271,8 @@ ofwfb_configure(int flags) return (0); if (OF_getproplen(node, "height") != sizeof(sc->sc_height) || - OF_getproplen(node, "width") != sizeof(sc->sc_width)) + OF_getproplen(node, "width") != sizeof(sc->sc_width) || + OF_getproplen(node, "linebytes") != sizeof(sc->sc_stride)) return (0); sc->sc_depth = depth; @@ -276,20 +283,6 @@ ofwfb_configure(int flags) OF_getprop(node, "linebytes", &sc->sc_stride, sizeof(sc->sc_stride)); /* - * Grab the physical address of the framebuffer, and then map it - * into our memory space. If the MMU is not yet up, it will be - * remapped for us when relocation turns on. - * - * XXX We assume #address-cells is 1 at this point. - */ - if (OF_getproplen(node, "address") != sizeof(fb_phys)) - return (0); - OF_getprop(node, "address", &fb_phys, sizeof(fb_phys)); - - bus_space_map(&bs_be_tag, fb_phys, sc->sc_height * sc->sc_stride, - BUS_SPACE_MAP_PREFETCHABLE, &sc->sc_addr); - - /* * Get the PCI addresses of the adapter. The node may be the * child of the PCI device: in that case, try the parent for * the assigned-addresses property. @@ -300,9 +293,53 @@ ofwfb_configure(int flags) len = OF_getprop(OF_parent(node), "assigned-addresses", sc->sc_pciaddrs, sizeof(sc->sc_pciaddrs)); } + if (len == -1) + len = 0; + sc->sc_num_pciaddrs = len / sizeof(struct ofw_pci_register); - if (len != -1) { - sc->sc_num_pciaddrs = len / sizeof(struct ofw_pci_register); + /* + * Grab the physical address of the framebuffer, and then map it + * into our memory space. If the MMU is not yet up, it will be + * remapped for us when relocation turns on. + * + * XXX We assume #address-cells is 1 at this point. + */ + if (OF_getproplen(node, "address") == sizeof(fb_phys)) { + OF_getprop(node, "address", &fb_phys, sizeof(fb_phys)); + sc->sc_tag = &bs_be_tag; + bus_space_map(sc->sc_tag, fb_phys, sc->sc_height * + sc->sc_stride, BUS_SPACE_MAP_PREFETCHABLE, &sc->sc_addr); + } else { + /* + * Some IBM systems don't have an address property. Try to + * guess the framebuffer region from the assigned addresses. + * This is ugly, but there doesn't seem to be an alternative. + * Linux does the same thing. + */ + + fb_phys = sc->sc_num_pciaddrs; + for (i = 0; i < sc->sc_num_pciaddrs; i++) { + /* If it is too small, not the framebuffer */ + if (sc->sc_pciaddrs[i].size_lo < + sc->sc_stride*sc->sc_height) + continue; + /* If it is not memory, it isn't either */ + if (!(sc->sc_pciaddrs[i].phys_hi & + OFW_PCI_PHYS_HI_SPACE_MEM32)) + continue; + + /* This could be the framebuffer */ + fb_phys = i; + + /* If it is prefetchable, it certainly is */ + if (sc->sc_pciaddrs[i].phys_hi & + OFW_PCI_PHYS_HI_PREFETCHABLE) + break; + } + if (fb_phys == sc->sc_num_pciaddrs) + return (0); + + OF_decode_addr(node, fb_phys, &sc->sc_tag, &sc->sc_addr); } ofwfb_init(0, &sc->sc_va, 0); @@ -617,13 +654,14 @@ ofwfb_blank_display32(video_adapter_t *adp, int mode) { struct ofwfb_softc *sc; int i; - uint32_t *addr; + uint32_t *addr, blank; sc = (struct ofwfb_softc *)adp; addr = (uint32_t *) sc->sc_addr; + blank = ofwfb_pix32(sc, ofwfb_background(SC_NORM_ATTR)); for (i = 0; i < (sc->sc_stride/4)*sc->sc_height; i++) - *(addr + i) = ofwfb_pix32(ofwfb_background(SC_NORM_ATTR)); + *(addr + i) = blank; return (0); } @@ -821,7 +859,7 @@ ofwfb_putc32(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) int row; int col; int i, j, k; - uint32_t *addr; + uint32_t *addr, fg, bg; u_char *p; sc = (struct ofwfb_softc *)adp; @@ -831,13 +869,16 @@ ofwfb_putc32(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) addr = (uint32_t *)sc->sc_addr + (row + sc->sc_ymargin)*(sc->sc_stride/4) + col + sc->sc_xmargin; + + fg = ofwfb_pix32(sc, ofwfb_foreground(a)); + bg = ofwfb_pix32(sc, ofwfb_background(a)); for (i = 0; i < sc->sc_font_height; i++) { for (j = 0, k = 7; j < 8; j++, k--) { if ((p[i] & (1 << k)) == 0) - *(addr + j) = ofwfb_pix32(ofwfb_background(a)); + *(addr + j) = bg; else - *(addr + j) = ofwfb_pix32(ofwfb_foreground(a)); + *(addr + j) = fg; } addr += (sc->sc_stride/4); } @@ -928,8 +969,8 @@ ofwfb_putm32(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, + (y + sc->sc_ymargin)*(sc->sc_stride/4) + x + sc->sc_xmargin; - fg = ofwfb_pix32(ofwfb_foreground(SC_NORM_ATTR)); - bg = ofwfb_pix32(ofwfb_background(SC_NORM_ATTR)); + fg = ofwfb_pix32(sc, ofwfb_foreground(SC_NORM_ATTR)); + bg = ofwfb_pix32(sc, ofwfb_background(SC_NORM_ATTR)); for (i = 0; i < size && i+y < sc->sc_height - 2*sc->sc_ymargin; i++) { for (j = 0, k = width; j < 8; j++, k--) { diff --git a/sys/powerpc/ofw/ofw_syscons.h b/sys/powerpc/ofw/ofw_syscons.h index 01b9727..f907f93 100644 --- a/sys/powerpc/ofw/ofw_syscons.h +++ b/sys/powerpc/ofw/ofw_syscons.h @@ -32,6 +32,7 @@ struct ofwfb_softc { video_adapter_t sc_va; struct cdev *sc_si; + bus_space_tag_t sc_tag; phandle_t sc_node; int sc_console; -- cgit v1.1