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:
parent
dbd2830c65
commit
023864f69c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=255904
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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--) {
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user