/* $NetBSD: ofw_rascons.c,v 1.8 2012/02/01 09:54:03 matt 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 __KERNEL_RCSID(0, "$NetBSD: ofw_rascons.c,v 1.8 2012/02/01 09:54:03 matt Exp $"); #include "wsdisplay.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* we need a wsdisplay to do anything halfway useful */ #if NWSDISPLAY > 0 #if defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE) int rascons_enable_cache = 0; #else #ifdef OFB_ENABLE_CACHE int rascons_enable_cache = 1; #else int rascons_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 rascons_console_screen; struct wsscreen_descr rascons_stdscreen = { "std", 0, 0, /* will be filled in -- XXX shouldn't, it's global */ 0, 0, 0, WSSCREEN_REVERSE }; int rascons_cnattach(void) { struct rasops_info *ri = &rascons_console_screen.scr_ri; long defattr; int crow = 0; /* 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 */ rascons_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 rascons_stdscreen.nrows = ri->ri_rows; rascons_stdscreen.ncols = ri->ri_cols; rascons_stdscreen.textops = &ri->ri_ops; rascons_stdscreen.capabilities = ri->ri_caps; ri->ri_ops.allocattr(ri, 0, 0, 0, &defattr); wsdisplay_preattach(&rascons_stdscreen, ri, 0, max(0, min(crow, ri->ri_rows - 1)), defattr); #if notyet rascons_init_cmap(NULL); #endif return 0; } static int copy_rom_font(void) { 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 rascons_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 (rascons_enable_cache) { vaddr_t va; /* * Let's try to find an empty 256M BAT to use */ for (va = SEGMENT_LENGTH; va < (USER_SR << ADDR_SR_SHFT); va += SEGMENT_LENGTH) { const u_int i = BAT_VA2IDX(va); const u_int n = BAT_VA2IDX(SEGMENT_LENGTH); u_int j; for (j = 0; j < n; j++) { if (battable[i+j].batu != 0) { break; } } if (j == n) { register_t batl = BATL(fbaddr & 0xf0000000, BAT_G | BAT_W | BAT_M, BAT_PP_RW); register_t batu = BATL(va, BAT_BL_256M, BAT_Vs); for (j = 0; j < n; j++) { battable[i+j].batl = batl; battable[i+j].batu = batu; } fbaddr &= SEGMENT_MASK; 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 | RI_NO_AUTO; /* mimic firmware output if we can find the ROM font */ if (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 rascons_cnattach(void) { return -1; } #endif