svn commit: r255904 - head/sys/powerpc/ofw

Nathan Whitehorn nwhitehorn at FreeBSD.org
Thu Sep 26 22:47:03 UTC 2013


Author: nwhitehorn
Date: Thu Sep 26 22:47:02 2013
New Revision: 255904
URL: http://svnweb.freebsd.org/changeset/base/255904

Log:
  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)

Modified:
  head/sys/powerpc/ofw/ofw_machdep.c
  head/sys/powerpc/ofw/ofw_syscons.c
  head/sys/powerpc/ofw/ofw_syscons.h

Modified: head/sys/powerpc/ofw/ofw_machdep.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_machdep.c	Thu Sep 26 21:18:46 2013	(r255903)
+++ head/sys/powerpc/ofw/ofw_machdep.c	Thu Sep 26 22:47:02 2013	(r255904)
@@ -680,7 +680,7 @@ OF_decode_addr(phandle_t dev, int regno,
 	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,
 	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,
 	}
 
 	*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));
 }
 

Modified: head/sys/powerpc/ofw/ofw_syscons.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_syscons.c	Thu Sep 26 21:18:46 2013	(r255903)
+++ head/sys/powerpc/ofw/ofw_syscons.c	Thu Sep 26 22:47:02 2013	(r255904)
@@ -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 *a
 {
 	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_of
 	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_of
 	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
 		+ (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--) {

Modified: head/sys/powerpc/ofw/ofw_syscons.h
==============================================================================
--- head/sys/powerpc/ofw/ofw_syscons.h	Thu Sep 26 21:18:46 2013	(r255903)
+++ head/sys/powerpc/ofw/ofw_syscons.h	Thu Sep 26 22:47:02 2013	(r255904)
@@ -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;
 


More information about the svn-src-head mailing list