NetBSD/sys/arch/macppc/dev/ofb_cons.c

269 lines
6.9 KiB
C

/* $NetBSD: ofb_cons.c,v 1.7 2007/02/28 04:21:51 thorpej Exp $ */
/*
* Copyright (c) 1995, 1996 Carnegie-Mellon University.
* All rights reserved.
*
* Author: Chris G. Demetriou
*
* Permission to use, copy, modify and distribute this software and
* its documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ofb_cons.c,v 1.7 2007/02/28 04:21:51 thorpej Exp $");
#include <sys/param.h>
#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/device.h>
#include <sys/ioctl.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/systm.h>
#include <powerpc/oea/bat.h>
#include <dev/ofw/openfirm.h>
#include <uvm/uvm_extern.h>
#include <machine/bus.h>
#include <machine/autoconf.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/rasops/rasops.h>
#include <dev/wsfont/wsfont.h>
#include <dev/wscons/wsdisplay_vconsvar.h>
#include <macppc/dev/ofbvar.h>
#include "wsdisplay.h"
/* we need a wsdisplay to do anything halfway useful */
#if NWSDISPLAY > 0
#if defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
int ofb_enable_cache = 0;
#else
#ifdef OFB_ENABLE_CACHE
int ofb_enable_cache = 1;
#else
int ofb_enable_cache = 0;
#endif
#endif /* PPC_OEA64 */
static int copy_rom_font(void);
static struct wsdisplay_font openfirm6x11;
static vaddr_t fbaddr;
static int romfont_loaded = 0;
struct vcons_screen ofb_console_screen;
struct wsscreen_descr ofb_stdscreen = {
"std",
0, 0, /* will be filled in -- XXX shouldn't, it's global */
0,
0, 0,
WSSCREEN_REVERSE
};
int
ofb_cnattach()
{
struct rasops_info *ri = &ofb_console_screen.scr_ri;
long defattr;
int crow = 0;
char type[16];
OF_getprop(console_node, "device_type", type, sizeof(type));
if (strcmp(type, "display") != 0)
return -1;
/* get current cursor position */
OF_interpret("line#", 0, 1, &crow);
/* move (rom monitor) cursor to the lowest line - 1 */
OF_interpret("#lines 2 - to line#", 0, 0);
wsfont_init();
if (copy_rom_font() == 0) {
romfont_loaded = 1;
}
/* set up rasops */
ofb_init_rasops(console_node, ri);
/*
* no need to clear the screen here when we're mimicing firmware
* output anyway
*/
#if 0
if (ri->ri_width >= 1024 && ri->ri_height >= 768) {
int i, screenbytes = ri->ri_stride * ri->ri_height;
for (i = 0; i < screenbytes; i += sizeof(u_int32_t))
*(u_int32_t *)(fbaddr + i) = 0xffffffff;
crow = 0;
}
#endif
ofb_stdscreen.nrows = ri->ri_rows;
ofb_stdscreen.ncols = ri->ri_cols;
ofb_stdscreen.textops = &ri->ri_ops;
ofb_stdscreen.capabilities = ri->ri_caps;
ri->ri_ops.allocattr(ri, 0, 0, 0, &defattr);
wsdisplay_preattach(&ofb_stdscreen, ri, 0, max(0,
min(crow, ri->ri_rows - 1)), defattr);
#if notyet
ofb_init_cmap(NULL);
#endif
return 0;
}
static int
copy_rom_font()
{
u_char *romfont;
int char_width, char_height;
int chosen, mmu, m, e;
/* Get ROM FONT address. */
OF_interpret("font-adr", 0, 1, &romfont);
if (romfont == NULL)
return -1;
chosen = OF_finddevice("/chosen");
OF_getprop(chosen, "mmu", &mmu, 4);
/*
* Convert to physcal address. We cannot access to Open Firmware's
* virtual address space.
*/
OF_call_method("translate", mmu, 1, 3, romfont, &romfont, &m, &e);
/* Get character size */
OF_interpret("char-width", 0, 1, &char_width);
OF_interpret("char-height", 0, 1, &char_height);
openfirm6x11.name = "Open Firmware";
openfirm6x11.firstchar = 32;
openfirm6x11.numchars = 96;
openfirm6x11.encoding = WSDISPLAY_FONTENC_ISO;
openfirm6x11.fontwidth = char_width;
openfirm6x11.fontheight = char_height;
openfirm6x11.stride = 1;
openfirm6x11.bitorder = WSDISPLAY_FONTORDER_L2R;
openfirm6x11.byteorder = WSDISPLAY_FONTORDER_L2R;
openfirm6x11.data = romfont;
return 0;
}
int
ofb_init_rasops(int node, struct rasops_info *ri)
{
int32_t width, height, linebytes, depth;
/* XXX /chaos/control doesn't have "width", "height", ... */
width = height = -1;
if (OF_getprop(node, "width", &width, 4) != 4)
OF_interpret("screen-width", 0, 1, &width);
if (OF_getprop(node, "height", &height, 4) != 4)
OF_interpret("screen-height", 0, 1, &height);
if (OF_getprop(node, "linebytes", &linebytes, 4) != 4)
linebytes = width; /* XXX */
if (OF_getprop(node, "depth", &depth, 4) != 4)
depth = 8; /* XXX */
if (OF_getprop(node, "address", &fbaddr, 4) != 4)
OF_interpret("frame-buffer-adr", 0, 1, &fbaddr);
if (width == -1 || height == -1 || fbaddr == 0 || fbaddr == -1)
return false;
/* Enable write-through cache. */
#if defined (PPC_OEA) && !defined (PPC_OEA64) && !defined (PPC_OEA64_BRIDGE)
if (ofb_enable_cache) {
vaddr_t va;
/*
* Let's try to find an empty BAT to use
*/
for (va = SEGMENT_LENGTH; va < (USER_SR << ADDR_SR_SHFT);
va += SEGMENT_LENGTH) {
if (battable[va >> ADDR_SR_SHFT].batu == 0) {
battable[va >> ADDR_SR_SHFT].batl =
BATL(fbaddr & 0xf0000000,
BAT_G | BAT_W | BAT_M, BAT_PP_RW);
battable[va >> ADDR_SR_SHFT].batu =
BATL(va, BAT_BL_256M, BAT_Vs);
fbaddr &= 0x0fffffff;
fbaddr |= va;
break;
}
}
}
#endif /* PPC_OEA64 */
/* initialize rasops */
ri->ri_width = width;
ri->ri_height = height;
ri->ri_depth = depth;
ri->ri_stride = linebytes;
ri->ri_bits = (char *)fbaddr;
ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
/* If screen is smaller than 1024x768, use small font. */
if ((width < 1024 || height < 768) && (romfont_loaded)) {
int cols, rows;
/*
* XXX this assumes we're the console which may or may not
* be the case
*/
OF_interpret("#lines", 0, 1, &rows);
OF_interpret("#columns", 0, 1, &cols);
ri->ri_font = &openfirm6x11;
ri->ri_wsfcookie = -1; /* not using wsfont */
rasops_init(ri, rows, cols);
ri->ri_xorigin = (width - cols * ri->ri_font->fontwidth) >> 1;
ri->ri_yorigin = (height - rows * ri->ri_font->fontheight)
>> 1;
ri->ri_bits = (char *)fbaddr + ri->ri_xorigin +
ri->ri_stride * ri->ri_yorigin;
} else {
/* use as much of the screen as the font permits */
rasops_init(ri, height/8, width/8);
ri->ri_caps = WSSCREEN_WSCOLORS;
rasops_reconfig(ri, height / ri->ri_font->fontheight,
width / ri->ri_font->fontwidth);
}
return true;
}
#else /* NWSDISPLAY > 0 */
int
ofb_cnattach()
{
return -1;
}
#endif