1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-16 10:20:30 +00:00

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)
This commit is contained in:
Nathan Whitehorn 2013-09-26 22:47:02 +00:00
parent dbd2830c65
commit 023864f69c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=255904
3 changed files with 74 additions and 30 deletions

View File

@ -680,7 +680,7 @@ OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag,
bus_size_t size, rsize; bus_size_t size, rsize;
uint32_t c, nbridge, naddr, nsize; uint32_t c, nbridge, naddr, nsize;
phandle_t bridge, parent; phandle_t bridge, parent;
u_int spc, rspc; u_int spc, rspc, prefetch;
int pci, pcib, res; int pci, pcib, res;
/* Sanity checking. */ /* Sanity checking. */
@ -707,6 +707,7 @@ OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag,
if (regno + naddr + nsize > res) if (regno + naddr + nsize > res)
return (EINVAL); return (EINVAL);
spc = (pci) ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK : ~0; spc = (pci) ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK : ~0;
prefetch = (pci) ? cell[regno] & OFW_PCI_PHYS_HI_PREFETCHABLE : 0;
addr = 0; addr = 0;
for (c = 0; c < naddr; c++) for (c = 0; c < naddr; c++)
addr = ((uint64_t)addr << 32) | cell[regno++]; 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; *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));
} }

View File

@ -199,13 +199,18 @@ ofwfb_foreground(uint8_t attr)
} }
static u_int static u_int
ofwfb_pix32(int attr) ofwfb_pix32(struct ofwfb_softc *sc, int attr)
{ {
u_int retval; u_int retval;
retval = (ofwfb_cmap[attr].blue << 16) | if (sc->sc_tag == &bs_le_tag)
(ofwfb_cmap[attr].green << 8) | retval = (ofwfb_cmap[attr].red << 16) |
ofwfb_cmap[attr].red; (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); return (retval);
} }
@ -221,6 +226,7 @@ ofwfb_configure(int flags)
int depth; int depth;
int disable; int disable;
int len; int len;
int i;
char type[16]; char type[16];
static int done = 0; static int done = 0;
@ -265,7 +271,8 @@ ofwfb_configure(int flags)
return (0); return (0);
if (OF_getproplen(node, "height") != sizeof(sc->sc_height) || 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); return (0);
sc->sc_depth = depth; sc->sc_depth = depth;
@ -275,20 +282,6 @@ ofwfb_configure(int flags)
OF_getprop(node, "width", &sc->sc_width, sizeof(sc->sc_width)); OF_getprop(node, "width", &sc->sc_width, sizeof(sc->sc_width));
OF_getprop(node, "linebytes", &sc->sc_stride, sizeof(sc->sc_stride)); 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 * Get the PCI addresses of the adapter. The node may be the
* child of the PCI device: in that case, try the parent for * child of the PCI device: in that case, try the parent for
@ -300,9 +293,53 @@ ofwfb_configure(int flags)
len = OF_getprop(OF_parent(node), "assigned-addresses", len = OF_getprop(OF_parent(node), "assigned-addresses",
sc->sc_pciaddrs, sizeof(sc->sc_pciaddrs)); 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); ofwfb_init(0, &sc->sc_va, 0);
@ -617,13 +654,14 @@ ofwfb_blank_display32(video_adapter_t *adp, int mode)
{ {
struct ofwfb_softc *sc; struct ofwfb_softc *sc;
int i; int i;
uint32_t *addr; uint32_t *addr, blank;
sc = (struct ofwfb_softc *)adp; sc = (struct ofwfb_softc *)adp;
addr = (uint32_t *) sc->sc_addr; 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++) 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); 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 row;
int col; int col;
int i, j, k; int i, j, k;
uint32_t *addr; uint32_t *addr, fg, bg;
u_char *p; u_char *p;
sc = (struct ofwfb_softc *)adp; 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 addr = (uint32_t *)sc->sc_addr
+ (row + sc->sc_ymargin)*(sc->sc_stride/4) + (row + sc->sc_ymargin)*(sc->sc_stride/4)
+ col + sc->sc_xmargin; + 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 (i = 0; i < sc->sc_font_height; i++) {
for (j = 0, k = 7; j < 8; j++, k--) { for (j = 0, k = 7; j < 8; j++, k--) {
if ((p[i] & (1 << k)) == 0) if ((p[i] & (1 << k)) == 0)
*(addr + j) = ofwfb_pix32(ofwfb_background(a)); *(addr + j) = bg;
else else
*(addr + j) = ofwfb_pix32(ofwfb_foreground(a)); *(addr + j) = fg;
} }
addr += (sc->sc_stride/4); 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) + (y + sc->sc_ymargin)*(sc->sc_stride/4)
+ x + sc->sc_xmargin; + x + sc->sc_xmargin;
fg = ofwfb_pix32(ofwfb_foreground(SC_NORM_ATTR)); fg = ofwfb_pix32(sc, ofwfb_foreground(SC_NORM_ATTR));
bg = ofwfb_pix32(ofwfb_background(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 (i = 0; i < size && i+y < sc->sc_height - 2*sc->sc_ymargin; i++) {
for (j = 0, k = width; j < 8; j++, k--) { for (j = 0, k = width; j < 8; j++, k--) {

View File

@ -32,6 +32,7 @@
struct ofwfb_softc { struct ofwfb_softc {
video_adapter_t sc_va; video_adapter_t sc_va;
struct cdev *sc_si; struct cdev *sc_si;
bus_space_tag_t sc_tag;
phandle_t sc_node; phandle_t sc_node;
int sc_console; int sc_console;