svn commit: r256681 - user/ed/newcons/sys/dev/vt/hw/ofwfb

Nathan Whitehorn nwhitehorn at FreeBSD.org
Thu Oct 17 12:15:22 UTC 2013


Author: nwhitehorn
Date: Thu Oct 17 12:15:21 2013
New Revision: 256681
URL: http://svnweb.freebsd.org/changeset/base/256681

Log:
  Sync with ofw_syscons.c: provide support for IBM framebuffers like that in
  the QEMU pSeries emulated platform.

Modified:
  user/ed/newcons/sys/dev/vt/hw/ofwfb/ofwfb.c

Modified: user/ed/newcons/sys/dev/vt/hw/ofwfb/ofwfb.c
==============================================================================
--- user/ed/newcons/sys/dev/vt/hw/ofwfb/ofwfb.c	Thu Oct 17 12:03:17 2013	(r256680)
+++ user/ed/newcons/sys/dev/vt/hw/ofwfb/ofwfb.c	Thu Oct 17 12:15:21 2013	(r256681)
@@ -52,9 +52,7 @@ struct ofwfb_softc {
 	int		sc_depth;
 	int		sc_stride;
 
-#ifdef __sparc64__
-	bus_space_tag_t	sc_memt;
-#endif
+	bus_space_tag_t sc_memt; 
 };
 
 static vd_init_t	ofwfb_init;
@@ -194,7 +192,10 @@ ofwfb_init(struct vt_device *vd)
 	ihandle_t stdout;
 	phandle_t node;
 	uint32_t depth, height, width;
+	struct ofw_pci_register pciaddrs[8];
+	int n_pciaddrs;
 	uint32_t fb_phys;
+	int i, len;
 #ifdef __sparc64__
 	static struct bus_space_tag ofwfb_memt[1];
 	bus_addr_t phys;
@@ -218,8 +219,17 @@ ofwfb_init(struct vt_device *vd)
 	/* Keep track of the OF node */
 	sc->sc_node = node;
 
+	/* Make sure we have needed properties */
+	if (OF_getproplen(node, "height") != sizeof(height) ||
+	    OF_getproplen(node, "width") != sizeof(width) ||
+	    OF_getproplen(node, "depth") != sizeof(depth) ||
+	    OF_getproplen(node, "linebytes") != sizeof(sc->sc_stride))
+		return (CN_DEAD);
+
 	/* Only support 8 and 32-bit framebuffers */
 	OF_getprop(node, "depth", &depth, sizeof(depth));
+	if (depth != 8 && depth != 32)
+		return (CN_DEAD);
 	sc->sc_depth = depth;
 
 	OF_getprop(node, "height", &height, sizeof(height));
@@ -230,24 +240,77 @@ ofwfb_init(struct vt_device *vd)
 	vd->vd_width = width;
 
 	/*
+	 * Get the PCI addresses of the adapter, if present. The node may be the
+	 * child of the PCI device: in that case, try the parent for
+	 * the assigned-addresses property.
+	 */
+	len = OF_getprop(node, "assigned-addresses", pciaddrs,
+	    sizeof(pciaddrs));
+	if (len == -1) {
+		len = OF_getprop(OF_parent(node), "assigned-addresses",
+		    pciaddrs, sizeof(pciaddrs));
+        }
+        if (len == -1)
+                len = 0;
+	n_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));
+	#if defined(__powerpc__)
+		sc->sc_memt = &bs_be_tag;
+		bus_space_map(sc->sc_memt, fb_phys, height * sc->sc_stride,
+		    BUS_SPACE_MAP_PREFETCHABLE, &sc->sc_addr);
+	#elif defined(__sparc64__)
+		OF_decode_addr(node, 0, &space, &phys);
+		sc->sc_memt = &ofwfb_memt[0];
+		sc->sc_addr = sparc64_fake_bustag(space, fb_phys, sc->sc_memt);
+	#else
+		#error Unsupported platform!
+	#endif
+	} 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.
+		 */
 
-	 /* XXX We assume #address-cells is 1 at this point. */
-	OF_getprop(node, "address", &fb_phys, sizeof(fb_phys));
+		fb_phys = n_pciaddrs;
+		for (i = 0; i < n_pciaddrs; i++) {
+			/* If it is too small, not the framebuffer */
+			if (pciaddrs[i].size_lo < sc->sc_stride*height)
+				continue;
+			/* If it is not memory, it isn't either */
+			if (!(pciaddrs[i].phys_hi &
+			    OFW_PCI_PHYS_HI_SPACE_MEM32))
+				continue;
 
-#if defined(__powerpc__)
-	bus_space_map(&bs_be_tag, fb_phys, height * sc->sc_stride,
-	    BUS_SPACE_MAP_PREFETCHABLE, &sc->sc_addr);
-#elif defined(__sparc64__)
-	OF_decode_addr(node, 0, &space, &phys);
-	sc->sc_memt = &ofwfb_memt[0];
-	sc->sc_addr = sparc64_fake_bustag(space, fb_phys, sc->sc_memt);
-#else
-	#error Unsupported platform!
-#endif
+			/* This could be the framebuffer */
+			fb_phys = i;
+
+			/* If it is prefetchable, it certainly is */
+			if (pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_PREFETCHABLE)
+				break;
+		}
+
+		if (fb_phys == n_pciaddrs) /* No candidates found */
+			return (CN_DEAD);
+
+	#if defined(__powerpc__)
+		OF_decode_addr(node, fb_phys, &sc->sc_memt, &sc->sc_addr);
+	#elif defined(__sparc64__)
+		OF_decode_addr(node, fb_phys, &space, &phys);
+		sc->sc_memt = &ofwfb_memt[0];
+		sc->sc_addr = sparc64_fake_bustag(space, phys, sc->sc_memt);
+	#endif
+        }
 
 	ofwfb_initialize(vd);
 


More information about the svn-src-user mailing list