148104Syokota/*- 248104Syokota * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 348104Syokota * All rights reserved. 448104Syokota * 548104Syokota * Redistribution and use in source and binary forms, with or without 648104Syokota * modification, are permitted provided that the following conditions 748104Syokota * are met: 848104Syokota * 1. Redistributions of source code must retain the above copyright 948104Syokota * notice, this list of conditions and the following disclaimer as 1048104Syokota * the first lines of this file unmodified. 1148104Syokota * 2. Redistributions in binary form must reproduce the above copyright 1248104Syokota * notice, this list of conditions and the following disclaimer in the 1348104Syokota * documentation and/or other materials provided with the distribution. 1448104Syokota * 1548104Syokota * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 1648104Syokota * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1748104Syokota * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1848104Syokota * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 1948104Syokota * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2048104Syokota * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2148104Syokota * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2248104Syokota * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2348104Syokota * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2448104Syokota * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2548104Syokota * 2685810Sobrien * Copyright (c) 2000 Andrew Miklic 2748104Syokota */ 2848104Syokota 2985810Sobrien#include <sys/cdefs.h> 3085810Sobrien__FBSDID("$FreeBSD$"); 3185810Sobrien 3248104Syokota#include "opt_syscons.h" 3385810Sobrien#include "opt_gfb.h" 34124770Sgrehan#ifdef __powerpc__ 35124770Sgrehan#include "opt_ofwfb.h" 36124770Sgrehan#endif 3748104Syokota 3848104Syokota#include <sys/param.h> 3948104Syokota#include <sys/systm.h> 4048104Syokota#include <sys/kernel.h> 4166834Sphk#include <sys/fbio.h> 4266834Sphk#include <sys/consio.h> 4348104Syokota 4465176Sdfr#include <machine/bus.h> 4548104Syokota 4648104Syokota#include <dev/fb/fbreg.h> 4748104Syokota#include <dev/syscons/syscons.h> 4848104Syokota 4948104Syokota#ifndef SC_RENDER_DEBUG 5048104Syokota#define SC_RENDER_DEBUG 0 5148104Syokota#endif 5248104Syokota 5385810Sobrienstatic vr_clear_t gfb_clear; 5485810Sobrienstatic vr_draw_border_t gfb_border; 5585810Sobrienstatic vr_draw_t gfb_draw; 5685810Sobrienstatic vr_set_cursor_t gfb_cursor_shape; 5785810Sobrienstatic vr_draw_cursor_t gfb_cursor; 5885810Sobrienstatic vr_blink_cursor_t gfb_blink; 5948104Syokota#ifndef SC_NO_CUTPASTE 6085810Sobrienstatic vr_draw_mouse_t gfb_mouse; 6148104Syokota#else 6285810Sobrien#define gfb_mouse (vr_draw_mouse_t *)gfb_nop 6348104Syokota#endif 6448104Syokota 65147358Speterstatic void gfb_nop(scr_stat *scp); 6648104Syokota 6785810Sobriensc_rndr_sw_t txtrndrsw = { 68146746Smarius (vr_init_t *)gfb_nop, 6985810Sobrien gfb_clear, 7085810Sobrien gfb_border, 7185810Sobrien gfb_draw, 7285810Sobrien gfb_cursor_shape, 7385810Sobrien gfb_cursor, 7485810Sobrien gfb_blink, 7585810Sobrien (vr_set_mouse_t *)gfb_nop, 7685810Sobrien gfb_mouse, 7748104Syokota}; 7848104Syokota 7948104Syokota#ifdef SC_PIXEL_MODE 8085810Sobriensc_rndr_sw_t gfbrndrsw = { 81146746Smarius (vr_init_t *)gfb_nop, 8285810Sobrien gfb_clear, 8385810Sobrien gfb_border, 8485810Sobrien gfb_draw, 8585810Sobrien gfb_cursor_shape, 8685810Sobrien gfb_cursor, 8785810Sobrien gfb_blink, 8885810Sobrien (vr_set_mouse_t *)gfb_nop, 8985810Sobrien gfb_mouse, 9048104Syokota}; 9148104Syokota#endif /* SC_PIXEL_MODE */ 9248104Syokota 9348104Syokota#ifndef SC_NO_MODE_CHANGE 9485810Sobriensc_rndr_sw_t grrndrsw = { 95146746Smarius (vr_init_t *)gfb_nop, 9685810Sobrien (vr_clear_t *)gfb_nop, 9785810Sobrien gfb_border, 9885810Sobrien (vr_draw_t *)gfb_nop, 9985810Sobrien (vr_set_cursor_t *)gfb_nop, 10085810Sobrien (vr_draw_cursor_t *)gfb_nop, 10185810Sobrien (vr_blink_cursor_t *)gfb_nop, 10285810Sobrien (vr_set_mouse_t *)gfb_nop, 10385810Sobrien (vr_draw_mouse_t *)gfb_nop, 10448104Syokota}; 10548104Syokota#endif /* SC_NO_MODE_CHANGE */ 10648104Syokota 10785810Sobrien#ifndef SC_NO_CUTPASTE 108170932Smarius#ifdef __sparc64__ 109170932Smariusstatic u_char mouse_pointer[22 * 2] = { 110170932Smarius 0x00, 0x00, /* ............ */ 111170932Smarius 0x80, 0x00, /* *........... */ 112170932Smarius 0xc0, 0x00, /* **.......... */ 113170932Smarius 0xe0, 0x00, /* ***......... */ 114170932Smarius 0xf0, 0x00, /* ****........ */ 115170932Smarius 0xf8, 0x00, /* *****....... */ 116170932Smarius 0xfc, 0x00, /* ******...... */ 117170932Smarius 0xfe, 0x00, /* *******..... */ 118170932Smarius 0xff, 0x00, /* ********.... */ 119170932Smarius 0xff, 0x80, /* *********... */ 120170932Smarius 0xfc, 0xc0, /* ******..**.. */ 121170932Smarius 0xdc, 0x00, /* **.***...... */ 122170932Smarius 0x8e, 0x00, /* *...***..... */ 123170932Smarius 0x0e, 0x00, /* ....***..... */ 124170932Smarius 0x07, 0x00, /* .....***.... */ 125170932Smarius 0x04, 0x00, /* .....*...... */ 126170932Smarius 0x00, 0x00, /* ............ */ 127170932Smarius 0x00, 0x00, /* ............ */ 128170932Smarius 0x00, 0x00, /* ............ */ 129170932Smarius 0x00, 0x00, /* ............ */ 130170932Smarius 0x00, 0x00, /* ............ */ 131170932Smarius 0x00, 0x00 /* ............ */ 132170932Smarius}; 133170932Smarius#else 13485810Sobrienstatic u_char mouse_pointer[16] = { 13585810Sobrien 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68, 13685810Sobrien 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 13748104Syokota}; 13848104Syokota#endif 139170932Smarius#endif 14048104Syokota 14148104Syokotastatic void 142147358Spetergfb_nop(scr_stat *scp) 14348104Syokota{ 14448104Syokota} 14548104Syokota 14648104Syokota/* text mode renderer */ 14748104Syokota 14848104Syokotastatic void 14985810Sobriengfb_clear(scr_stat *scp, int c, int attr) 15048104Syokota{ 151174985Swkoszek vidd_clear(scp->sc->adp); 15248104Syokota} 15348104Syokota 15448104Syokotastatic void 15585810Sobriengfb_border(scr_stat *scp, int color) 15648104Syokota{ 157174985Swkoszek vidd_set_border(scp->sc->adp, color); 15848104Syokota} 15948104Syokota 16048104Syokotastatic void 16185810Sobriengfb_draw(scr_stat *scp, int from, int count, int flip) 16248104Syokota{ 163119383Sjake int c; 164119383Sjake int a; 16585810Sobrien int i, n; 16685810Sobrien video_adapter_t *adp; 16748104Syokota 16885810Sobrien adp = scp->sc->adp; 16948104Syokota 17085810Sobrien /* 17185810Sobrien Determine if we need to scroll based on the offset 17285810Sobrien and the number of characters to be displayed... 17385810Sobrien */ 17485810Sobrien if (from + count > scp->xsize*scp->ysize) { 17585810Sobrien 17685810Sobrien /* 17785810Sobrien Calculate the number of characters past the end of the 17885810Sobrien visible screen... 17985810Sobrien */ 18085810Sobrien count = (from + count) - 18185810Sobrien (adp->va_info.vi_width * adp->va_info.vi_height); 18285810Sobrien 18385810Sobrien /* 18485810Sobrien Calculate the number of rows past the end of the visible 18585810Sobrien screen... 18685810Sobrien */ 18785810Sobrien n = (count / adp->va_info.vi_width) + 1; 18885810Sobrien 18985810Sobrien /* Scroll to make room for new text rows... */ 190174985Swkoszek vidd_copy(adp, n, 0, n); 19190664Sgallatin#if 0 192174985Swkoszek vidd_clear(adp, n); 19385810Sobrien#endif 19485810Sobrien 19585810Sobrien /* Display new text rows... */ 196174985Swkoszek vidd_puts(adp, from, 19785810Sobrien (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), count); 19885810Sobrien } 19985810Sobrien 20085810Sobrien /* 20185810Sobrien We don't need to scroll, so we can just put the characters 20285810Sobrien all-at-once... 20385810Sobrien */ 20485810Sobrien else { 20585810Sobrien 20685810Sobrien /* 20785810Sobrien Determine the method by which we are to display characters 20885810Sobrien (are we going to print forwards or backwards? 20985810Sobrien do we need to do a character-by-character copy, then?)... 21085810Sobrien */ 21185810Sobrien if (flip) 21285810Sobrien for (i = count; i-- > 0; ++from) { 21385810Sobrien c = sc_vtb_getc(&scp->vtb, from); 21485810Sobrien a = sc_vtb_geta(&scp->vtb, from) >> 8; 215174985Swkoszek vidd_putc(adp, from, c, 216119383Sjake (a >> 4) | ((a & 0xf) << 4)); 21785810Sobrien } 21885810Sobrien else { 219174985Swkoszek vidd_puts(adp, from, 22085810Sobrien (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), 22185810Sobrien count); 22248104Syokota } 22348104Syokota } 22448104Syokota} 22548104Syokota 22648104Syokotastatic void 22785810Sobriengfb_cursor_shape(scr_stat *scp, int base, int height, int blink) 22848104Syokota{ 22948104Syokota if (base < 0 || base >= scp->font_size) 23048104Syokota return; 23148104Syokota /* the caller may set height <= 0 in order to disable the cursor */ 23248104Syokota#if 0 23385810Sobrien scp->cursor_base = base; 23485810Sobrien scp->cursor_height = height; 23548104Syokota#endif 236174985Swkoszek vidd_set_hw_cursor_shape(scp->sc->adp, base, height, scp->font_size, 237174985Swkoszek blink); 23848104Syokota} 23948104Syokota 24085810Sobrienstatic int pxlblinkrate = 0; 24158872Syokota 242146472Smarius#if defined(__sparc64__) || defined(SC_OFWFB) 24358872Syokotastatic void 24485810Sobriengfb_cursor(scr_stat *scp, int at, int blink, int on, int flip) 24548104Syokota{ 24648104Syokota video_adapter_t *adp; 247119383Sjake int a, c; 24848104Syokota 249119383Sjake if (scp->curs_attr.height <= 0) /* the text cursor is disabled */ 25048104Syokota return; 25148104Syokota 25248104Syokota adp = scp->sc->adp; 25385810Sobrien if(blink) { 25448104Syokota scp->status |= VR_CURSOR_BLINK; 25548104Syokota if (on) { 25648104Syokota scp->status |= VR_CURSOR_ON; 257174985Swkoszek vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize); 25848104Syokota } else { 25948104Syokota if (scp->status & VR_CURSOR_ON) 260174985Swkoszek vidd_set_hw_cursor(adp, -1, -1); 26148104Syokota scp->status &= ~VR_CURSOR_ON; 26248104Syokota } 26348104Syokota } else { 26448104Syokota scp->status &= ~VR_CURSOR_BLINK; 26585810Sobrien if(on) { 26648104Syokota scp->status |= VR_CURSOR_ON; 267174985Swkoszek vidd_putc(scp->sc->adp, scp->cursor_oldpos, 268119383Sjake sc_vtb_getc(&scp->vtb, scp->cursor_oldpos), 269119383Sjake sc_vtb_geta(&scp->vtb, scp->cursor_oldpos) >> 8); 270119383Sjake a = sc_vtb_geta(&scp->vtb, at) >> 8; 271119383Sjake c = sc_vtb_getc(&scp->vtb, at); 272174985Swkoszek vidd_putc(scp->sc->adp, at, c, 273174985Swkoszek (a >> 4) | ((a & 0xf) << 4)); 274119383Sjake scp->cursor_saveunder_attr = a; 275119383Sjake scp->cursor_saveunder_char = c; 27648104Syokota } else { 27748104Syokota if (scp->status & VR_CURSOR_ON) 278174985Swkoszek vidd_putc(scp->sc->adp, at, 279174985Swkoszek scp->cursor_saveunder_char, 28085810Sobrien scp->cursor_saveunder_attr); 28148104Syokota scp->status &= ~VR_CURSOR_ON; 28248104Syokota } 28348104Syokota } 28448104Syokota} 285119383Sjake#else 28648104Syokotastatic void 28785810Sobriengfb_cursor(scr_stat *scp, int at, int blink, int on, int flip) 28848104Syokota{ 28985810Sobrien video_adapter_t *adp; 29048104Syokota 29185810Sobrien adp = scp->sc->adp; 29294617Sobrien if (scp->curs_attr.height <= 0) 29394617Sobrien /* the text cursor is disabled */ 29448104Syokota return; 29548104Syokota 29648104Syokota if (on) { 29758232Syokota if (!blink) { 29858232Syokota scp->status |= VR_CURSOR_ON; 299174985Swkoszek vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize); 30058232Syokota } else if (++pxlblinkrate & 4) { 30158232Syokota pxlblinkrate = 0; 30258232Syokota scp->status ^= VR_CURSOR_ON; 30385810Sobrien if(scp->status & VR_CURSOR_ON) 304174985Swkoszek vidd_set_hw_cursor(adp, at%scp->xsize, 305174985Swkoszek at/scp->xsize); 30685810Sobrien else 307174985Swkoszek vidd_set_hw_cursor(adp, -1, -1); 30858232Syokota } 30948104Syokota } else { 31048104Syokota if (scp->status & VR_CURSOR_ON) 311174985Swkoszek vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize); 31248104Syokota scp->status &= ~VR_CURSOR_ON; 31348104Syokota } 31448104Syokota if (blink) 31548104Syokota scp->status |= VR_CURSOR_BLINK; 31648104Syokota else 31748104Syokota scp->status &= ~VR_CURSOR_BLINK; 31848104Syokota} 319119383Sjake#endif 32048104Syokota 32148104Syokotastatic void 32285810Sobriengfb_blink(scr_stat *scp, int at, int flip) 32348104Syokota{ 32448104Syokota if (!(scp->status & VR_CURSOR_BLINK)) 32548104Syokota return; 32658232Syokota if (!(++pxlblinkrate & 4)) 32748104Syokota return; 32858232Syokota pxlblinkrate = 0; 32948104Syokota scp->status ^= VR_CURSOR_ON; 33085810Sobrien gfb_cursor(scp, at, scp->status & VR_CURSOR_BLINK, 33185810Sobrien scp->status & VR_CURSOR_ON, flip); 33248104Syokota} 33348104Syokota 33448104Syokota#ifndef SC_NO_CUTPASTE 33548104Syokota 33685810Sobrienstatic void 33785810Sobriengfb_mouse(scr_stat *scp, int x, int y, int on) 33848104Syokota{ 339170932Smarius#ifdef __sparc64__ 340174985Swkoszek vidd_putm(scp->sc->adp, x, y, mouse_pointer, 341174985Swkoszek on ? 0xffffffff : 0x0, 22, 12); 342170932Smarius#else 34385810Sobrien int i, pos; 34448104Syokota 34585810Sobrien if (on) { 34648104Syokota 34785810Sobrien /* Display the mouse pointer image... */ 348174985Swkoszek vidd_putm(scp->sc->adp, x, y, mouse_pointer, 349174985Swkoszek 0xffffffff, 16, 8); 35048104Syokota } else { 35148104Syokota 35285810Sobrien /* 35385810Sobrien Erase the mouse cursor image by redrawing the text 35485810Sobrien underneath it... 35585810Sobrien */ 35685810Sobrien return; 35785810Sobrien pos = x*scp->xsize + y; 35885810Sobrien i = (y < scp->xsize - 1) ? 2 : 1; 35985810Sobrien (*scp->rndr->draw)(scp, pos, i, FALSE); 36085810Sobrien if (x < scp->ysize - 1) 36185810Sobrien (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE); 36248104Syokota } 363170932Smarius#endif 36448104Syokota} 36548104Syokota 36648104Syokota#endif /* SC_NO_CUTPASTE */ 367