1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer as 12 * the first lines of this file unmodified. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Copyright (c) 2000 Andrew Miklic 29 */ 30 31#include <sys/cdefs.h> 32__FBSDID("$FreeBSD$"); 33 34#include "opt_syscons.h" 35#ifdef __powerpc__ 36#include "opt_ofwfb.h" 37#endif 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> 42#include <sys/fbio.h> 43#include <sys/consio.h> 44 45#include <machine/bus.h> 46 47#include <dev/fb/fbreg.h> 48#include <dev/syscons/syscons.h> 49 50#ifndef SC_RENDER_DEBUG 51#define SC_RENDER_DEBUG 0 52#endif 53 54static vr_clear_t gfb_clear; 55static vr_draw_border_t gfb_border; 56static vr_draw_t gfb_draw; 57static vr_set_cursor_t gfb_cursor_shape; 58static vr_draw_cursor_t gfb_cursor; 59static vr_blink_cursor_t gfb_blink; 60#ifndef SC_NO_CUTPASTE 61static vr_draw_mouse_t gfb_mouse; 62#else 63#define gfb_mouse (vr_draw_mouse_t *)gfb_nop 64#endif 65 66static void gfb_nop(scr_stat *scp); 67 68sc_rndr_sw_t txtrndrsw = { 69 (vr_init_t *)gfb_nop, 70 gfb_clear, 71 gfb_border, 72 gfb_draw, 73 gfb_cursor_shape, 74 gfb_cursor, 75 gfb_blink, 76 (vr_set_mouse_t *)gfb_nop, 77 gfb_mouse, 78}; 79 80#ifdef SC_PIXEL_MODE 81sc_rndr_sw_t gfbrndrsw = { 82 (vr_init_t *)gfb_nop, 83 gfb_clear, 84 gfb_border, 85 gfb_draw, 86 gfb_cursor_shape, 87 gfb_cursor, 88 gfb_blink, 89 (vr_set_mouse_t *)gfb_nop, 90 gfb_mouse, 91}; 92#endif /* SC_PIXEL_MODE */ 93 94#ifndef SC_NO_MODE_CHANGE 95sc_rndr_sw_t grrndrsw = { 96 (vr_init_t *)gfb_nop, 97 (vr_clear_t *)gfb_nop, 98 gfb_border, 99 (vr_draw_t *)gfb_nop, 100 (vr_set_cursor_t *)gfb_nop, 101 (vr_draw_cursor_t *)gfb_nop, 102 (vr_blink_cursor_t *)gfb_nop, 103 (vr_set_mouse_t *)gfb_nop, 104 (vr_draw_mouse_t *)gfb_nop, 105}; 106#endif /* SC_NO_MODE_CHANGE */ 107 108#ifndef SC_NO_CUTPASTE 109static u_char mouse_pointer[16] = { 110 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68, 111 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 112}; 113#endif 114 115static void 116gfb_nop(scr_stat *scp) 117{ 118} 119 120/* text mode renderer */ 121 122static void 123gfb_clear(scr_stat *scp, int c, int attr) 124{ 125 vidd_clear(scp->sc->adp); 126} 127 128static void 129gfb_border(scr_stat *scp, int color) 130{ 131 vidd_set_border(scp->sc->adp, color); 132} 133 134static void 135gfb_draw(scr_stat *scp, int from, int count, int flip) 136{ 137 int c; 138 int a; 139 int i, n; 140 video_adapter_t *adp; 141 142 adp = scp->sc->adp; 143 144 /* 145 Determine if we need to scroll based on the offset 146 and the number of characters to be displayed... 147 */ 148 if (from + count > scp->xsize*scp->ysize) { 149 /* 150 Calculate the number of characters past the end of the 151 visible screen... 152 */ 153 count = (from + count) - 154 (adp->va_info.vi_width * adp->va_info.vi_height); 155 156 /* 157 Calculate the number of rows past the end of the visible 158 screen... 159 */ 160 n = (count / adp->va_info.vi_width) + 1; 161 162 /* Scroll to make room for new text rows... */ 163 vidd_copy(adp, n, 0, n); 164#if 0 165 vidd_clear(adp, n); 166#endif 167 168 /* Display new text rows... */ 169 vidd_puts(adp, from, 170 (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), count); 171 } 172 173 /* 174 We don't need to scroll, so we can just put the characters 175 all-at-once... 176 */ 177 else { 178 /* 179 Determine the method by which we are to display characters 180 (are we going to print forwards or backwards? 181 do we need to do a character-by-character copy, then?)... 182 */ 183 if (flip) 184 for (i = count; i-- > 0; ++from) { 185 c = sc_vtb_getc(&scp->vtb, from); 186 a = sc_vtb_geta(&scp->vtb, from) >> 8; 187 vidd_putc(adp, from, c, 188 (a >> 4) | ((a & 0xf) << 4)); 189 } 190 else { 191 vidd_puts(adp, from, 192 (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), 193 count); 194 } 195 } 196} 197 198static void 199gfb_cursor_shape(scr_stat *scp, int base, int height, int blink) 200{ 201 if (base < 0 || base >= scp->font_size) 202 return; 203 /* the caller may set height <= 0 in order to disable the cursor */ 204#if 0 205 scp->cursor_base = base; 206 scp->cursor_height = height; 207#endif 208 vidd_set_hw_cursor_shape(scp->sc->adp, base, height, scp->font_size, 209 blink); 210} 211 212static int pxlblinkrate = 0; 213 214#if defined(SC_OFWFB) 215static void 216gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip) 217{ 218 video_adapter_t *adp; 219 int a, c; 220 221 if (scp->curs_attr.height <= 0) /* the text cursor is disabled */ 222 return; 223 224 adp = scp->sc->adp; 225 if(blink) { 226 scp->status |= VR_CURSOR_BLINK; 227 if (on) { 228 scp->status |= VR_CURSOR_ON; 229 vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize); 230 } else { 231 if (scp->status & VR_CURSOR_ON) 232 vidd_set_hw_cursor(adp, -1, -1); 233 scp->status &= ~VR_CURSOR_ON; 234 } 235 } else { 236 scp->status &= ~VR_CURSOR_BLINK; 237 if(on) { 238 scp->status |= VR_CURSOR_ON; 239 vidd_putc(scp->sc->adp, scp->cursor_oldpos, 240 sc_vtb_getc(&scp->vtb, scp->cursor_oldpos), 241 sc_vtb_geta(&scp->vtb, scp->cursor_oldpos) >> 8); 242 a = sc_vtb_geta(&scp->vtb, at) >> 8; 243 c = sc_vtb_getc(&scp->vtb, at); 244 vidd_putc(scp->sc->adp, at, c, 245 (a >> 4) | ((a & 0xf) << 4)); 246 } else { 247 if (scp->status & VR_CURSOR_ON) 248 vidd_putc(scp->sc->adp, at, 249 sc_vtb_getc(&scp->vtb, at), 250 sc_vtb_geta(&scp->vtb, at) >> 8); 251 scp->status &= ~VR_CURSOR_ON; 252 } 253 } 254} 255#else 256static void 257gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip) 258{ 259 video_adapter_t *adp; 260 261 adp = scp->sc->adp; 262 if (scp->curs_attr.height <= 0) 263 /* the text cursor is disabled */ 264 return; 265 266 if (on) { 267 if (!blink) { 268 scp->status |= VR_CURSOR_ON; 269 vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize); 270 } else if (++pxlblinkrate & 4) { 271 pxlblinkrate = 0; 272 scp->status ^= VR_CURSOR_ON; 273 if(scp->status & VR_CURSOR_ON) 274 vidd_set_hw_cursor(adp, at%scp->xsize, 275 at/scp->xsize); 276 else 277 vidd_set_hw_cursor(adp, -1, -1); 278 } 279 } else { 280 if (scp->status & VR_CURSOR_ON) 281 vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize); 282 scp->status &= ~VR_CURSOR_ON; 283 } 284 if (blink) 285 scp->status |= VR_CURSOR_BLINK; 286 else 287 scp->status &= ~VR_CURSOR_BLINK; 288} 289#endif 290 291static void 292gfb_blink(scr_stat *scp, int at, int flip) 293{ 294 if (!(scp->status & VR_CURSOR_BLINK)) 295 return; 296 if (!(++pxlblinkrate & 4)) 297 return; 298 pxlblinkrate = 0; 299 scp->status ^= VR_CURSOR_ON; 300 gfb_cursor(scp, at, scp->status & VR_CURSOR_BLINK, 301 scp->status & VR_CURSOR_ON, flip); 302} 303 304#ifndef SC_NO_CUTPASTE 305 306static void 307gfb_mouse(scr_stat *scp, int x, int y, int on) 308{ 309 if (on) { 310 vidd_putm(scp->sc->adp, x, y, mouse_pointer, 311 0xffffffff, 16, 8); 312 } else { 313 /* XXX: removal is incomplete for h/w cursors and borders. */ 314 } 315} 316 317#endif /* SC_NO_CUTPASTE */ 318