Add a vt(4) framebuffer for Open Firmware linear framebuffer devices (i.e.

all graphics on PowerPC Apple systems). This will also work on some sparc64
graphics hardware with a small amount of modification.
This commit is contained in:
nwhitehorn 2012-01-21 17:59:50 +00:00
parent 629157c416
commit 1fa9866b98
2 changed files with 240 additions and 1 deletions

View File

@ -30,7 +30,7 @@ dev/hwpmc/hwpmc_powerpc.c optional hwpmc
dev/iicbus/ad7417.c optional ad7417 powermac
dev/iicbus/ds1775.c optional ds1775 powermac
dev/iicbus/max6690.c optional max6690 powermac
dev/kbd/kbd.c optional sc
dev/kbd/kbd.c optional sc | vt
dev/ofw/openfirm.c optional aim | fdt
dev/ofw/openfirmio.c optional aim | fdt
dev/ofw/ofw_bus_if.m optional aim | fdt
@ -56,6 +56,7 @@ dev/syscons/scvtb.c optional sc
dev/tsec/if_tsec.c optional tsec
dev/tsec/if_tsec_fdt.c optional tsec fdt
dev/uart/uart_cpu_powerpc.c optional uart aim
dev/vt/hw/ofwfb/ofwfb.c optional vt aim
kern/kern_clocksource.c standard
kern/syscalls.c optional ktr
libkern/ashldi3.c optional powerpc

238
sys/dev/vt/hw/ofwfb/ofwfb.c Normal file
View File

@ -0,0 +1,238 @@
/*-
* Copyright (c) 2011 Nathan Whitehorn
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: user/ed/newcons/sys/dev/vt/hw/ofwfb/ofwfb.c 219888 2011-03-22 21:31:31Z ed $");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <dev/vt/vt.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/bus.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_pci.h>
struct ofwfb_softc {
phandle_t sc_node;
intptr_t sc_addr;
int sc_depth;
int sc_stride;
};
static vd_init_t ofwfb_init;
static vd_blank_t ofwfb_blank;
static vd_bitblt_t ofwfb_bitblt;
static const struct vt_driver vt_ofwfb_driver = {
.vd_init = ofwfb_init,
.vd_blank = ofwfb_blank,
.vd_bitblt = ofwfb_bitblt,
};
static struct ofwfb_softc ofwfb_conssoftc;
VT_CONSDEV_DECLARE(vt_ofwfb_driver, 1600, 1200, &ofwfb_conssoftc);
static const uint32_t colormap[] = {
0x00000000, /* Black */
0x00ff0000, /* Red */
0x0000ff00, /* Green */
0x00c0c000, /* Brown */
0x000000ff, /* Blue */
0x00c000c0, /* Magenta */
0x0000c0c0, /* Cyan */
0x00c0c0c0, /* Light grey */
0x00808080, /* Dark grey */
0x00ff8080, /* Light red */
0x0080ff80, /* Light green */
0x00ffff80, /* Yellow */
0x008080ff, /* Light blue */
0x00ff80ff, /* Light magenta */
0x0080ffff, /* Light cyan */
0x00ffffff, /* White */
};
static void
ofwfb_blank(struct vt_device *vd, term_color_t color)
{
struct ofwfb_softc *sc = vd->vd_softc;
u_int ofs;
uint32_t c;
switch (sc->sc_depth) {
case 8:
for (ofs = 0; ofs < sc->sc_stride*vd->vd_height; ofs++)
*(uint8_t *)(sc->sc_addr + ofs) = color;
break;
case 32:
c = colormap[color];
for (ofs = 0; ofs < sc->sc_stride*vd->vd_height; ofs++)
memcpy((void *)(sc->sc_addr + 4*ofs), &c, 4);
break;
default:
/* panic? */
break;
}
}
static void
ofwfb_bitblt(struct vt_device *vd, const uint8_t *src,
vt_axis_t top, vt_axis_t left, unsigned int width, unsigned int height,
term_color_t fg, term_color_t bg)
{
struct ofwfb_softc *sc = vd->vd_softc;
u_long line;
uint32_t fgc, bgc;
int c;
uint8_t b = 0;
fgc = colormap[fg];
bgc = colormap[bg];
line = (sc->sc_stride * top) + left * sc->sc_depth/8;
for (; height > 0; height--) {
line += sc->sc_stride;
for (c = 0; c < width; c++) {
if (c % 8 == 0)
b = *src++;
else
b <<= 1;
switch(sc->sc_depth) {
case 8:
*(uint8_t *)(sc->sc_addr + line + c) =
b & 0x80 ? fg : bg;
break;
case 32:
memcpy((void *)(sc->sc_addr + line + c*4),
b & 0x80 ? &fgc : &bgc, 4);
break;
default:
/* panic? */
break;
}
}
}
}
static void
ofwfb_initialize(struct vt_device *vd)
{
struct ofwfb_softc *sc = vd->vd_softc;
char name[64];
ihandle_t ih;
cell_t depth = 8;
int i, retval;
/* Open display device, thereby initializing it */
memset(name, 0, sizeof(name));
OF_package_to_path(sc->sc_node, name, sizeof(name));
ih = OF_open(name);
OF_getprop(sc->sc_node, "depth", &depth, sizeof(depth));
sc->sc_depth = depth;
if (sc->sc_depth == 8) {
/*
* Install the ISO6429 colormap - older OFW systems
* don't do this by default
*/
for (i = 0; i < 16; i++) {
OF_call_method("color!", ih, 4, 1,
(colormap[i] >> 16) & 0xff,
(colormap[i] >> 8) & 0xff,
(colormap[i] >> 0) & 0xff,
i,
&retval);
}
}
/* Clear the screen. */
ofwfb_blank(vd, TC_BLACK);
}
static int
ofwfb_init(struct vt_device *vd)
{
struct ofwfb_softc *sc = vd->vd_softc;
char type[64];
phandle_t chosen;
ihandle_t stdout;
phandle_t node;
cell_t depth, height, width;
uint32_t fb_phys;
chosen = OF_finddevice("/chosen");
OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
node = OF_instance_to_package(stdout);
if (node == -1) {
/*
* The "/chosen/stdout" does not exist try
* using "screen" directly.
*/
node = OF_finddevice("screen");
}
OF_getprop(node, "device_type", type, sizeof(type));
if (strcmp(type, "display") != 0)
return (CN_DEAD);
/* Keep track of the OF node */
sc->sc_node = node;
/* Only support 8 and 32-bit framebuffers */
OF_getprop(node, "depth", &depth, sizeof(depth));
sc->sc_depth = depth;
OF_getprop(node, "height", &height, sizeof(height));
OF_getprop(node, "width", &width, sizeof(width));
OF_getprop(node, "linebytes", &sc->sc_stride, sizeof(sc->sc_stride));
vd->vd_height = height;
vd->vd_width = width;
/*
* 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.
*/
OF_getprop(node, "address", &fb_phys, sizeof(fb_phys));
bus_space_map(&bs_be_tag, fb_phys, height * sc->sc_stride,
BUS_SPACE_MAP_PREFETCHABLE, &sc->sc_addr);
ofwfb_initialize(vd);
return (CN_INTERNAL);
}