/* $NetBSD: cons_fb.c,v 1.4 2008/04/28 20:23:18 martin Exp $ */ /*- * Copyright (c) 2004 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by UCHIYAMA Yasushi. * * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 #include #include #include #include #include "console.h" struct fb fb; void fb_set_addr(uint32_t fb_addr, uint32_t fb_size, uint32_t font_addr) { fb.fb_addr = (uint8_t *)fb_addr; fb.fb_size = fb_size; fb.font_addr = (uint8_t *)font_addr; cons.init = fb_init; cons.putc = fb_drawchar; cons.scroll = fb_scroll; cons.cursor = fb_drawcursor; } void * fb_get_addr(void) { return fb.fb_addr; } void fb_init(void) { cons.x = X_INIT; cons.y = Y_INIT; fb.active = true; fb_clear(0, 0, FB_WIDTH, FB_HEIGHT, CONS_BG); } void fb_active(bool on) { if (fb.active && !on) printf("FB disabled.\n"); fb.active = on; if (fb.active && on) printf("FB enabled.\n"); } void fb_scroll(void) { if (!fb.active) return; #if 0 /* 1-line scroll */ cons.y--; fb_copy(0, ROM_FONT_HEIGHT, 0, 0, FB_WIDTH, FB_HEIGHT * (CONS_HEIGHT - 1)); fb_clear(0, cons.y * ROM_FONT_HEIGHT, FB_WIDTH, ROM_FONT_HEIGHT, CONS_BG); #else /* jump scroll */ cons.y /= 2; fb_copy(0, cons.y * ROM_FONT_HEIGHT, 0, 0, FB_WIDTH, FB_HEIGHT / 2); fb_clear(0, cons.y *ROM_FONT_HEIGHT, FB_WIDTH, FB_HEIGHT / 2, CONS_BG); #endif } #define MINMAX(x, min, max) \ ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x))) void fb_clear(int x, int y, int w, int h, int q) { uint8_t *p; int i, j, k, xend, yend; if (!fb.active) return; x = MINMAX(x, 0, FB_WIDTH); y = MINMAX(y, 0, FB_HEIGHT); xend = MINMAX(x + w, 0, FB_WIDTH); yend = MINMAX(y + h , 0, FB_HEIGHT); p = (uint8_t *)fb.fb_addr + x + y * FB_LINEBYTES; j = xend - x; k = j + FB_LINEBYTES - w; for (i = y; i < yend; i++, p+= k) memset(p, q, j); } void fb_copy(int x0, int y0, int x1, int y1, int w, int h) { int x1end, y1end, i, j, k; uint8_t *p, *q; if (!fb.active) return; x0 = MINMAX(x0, 0, FB_WIDTH); y0 = MINMAX(y0, 0, FB_HEIGHT); x1 = MINMAX(x1, 0, FB_WIDTH); y1 = MINMAX(y1, 0, FB_HEIGHT); x1end = MINMAX(x1 + w, 0, FB_WIDTH); y1end = MINMAX(y1 + h, 0, FB_HEIGHT); p = fb.fb_addr + x1 + y1 * FB_LINEBYTES; q = fb.fb_addr + x0 + y0 * FB_LINEBYTES; j = x1end - x1; k = j + FB_LINEBYTES - w; for (i = y1; i < y1end; i++, p += k, q += k) memmove(p, q, j); } #undef MINMAX void fb_drawchar(int x, int y, int c) { uint16_t *font_addr; int font_ofs; if (!fb.active) return; if ((font_ofs = (c & 0x7f) - 0x20) < 0) return; font_addr = (uint16_t *)(fb.font_addr + font_ofs * sizeof(uint16_t) * ROM_FONT_HEIGHT); fb_drawfont(x, y, font_addr); } void fb_drawfont(int x, int y, uint16_t *font_addr) { uint8_t *fb_addr; uint16_t bitmap; int i, j; if (!fb.active) return; fb_addr = fb.fb_addr + x + y * FB_LINEBYTES; for (i = 0; i < 24; i++) { bitmap = *font_addr++; for (j = 0; j < 12; j++, bitmap <<= 1) fb_addr[j] = bitmap & 0x8000 ? CONS_FG : CONS_BG; fb_addr += FB_LINEBYTES; } } void fb_drawcursor(int x, int y) { uint8_t *fb_addr; int i, j; if (!fb.active) return; fb_addr = fb.fb_addr + x + y * FB_LINEBYTES; for (i = 0; i < 24; i++) { for (j = 0; j < 12; j++) fb_addr[j] = fb_addr[j] == CONS_FG ? CONS_BG : CONS_FG; fb_addr += FB_LINEBYTES; } }