1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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 #include "opt_syscons.h" 33 #ifdef __powerpc__ 34 #include "opt_ofwfb.h" 35 #endif 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/fbio.h> 41 #include <sys/consio.h> 42 43 #include <machine/bus.h> 44 45 #include <dev/fb/fbreg.h> 46 #include <dev/syscons/syscons.h> 47 48 #ifndef SC_RENDER_DEBUG 49 #define SC_RENDER_DEBUG 0 50 #endif 51 52 static vr_clear_t gfb_clear; 53 static vr_draw_border_t gfb_border; 54 static vr_draw_t gfb_draw; 55 static vr_set_cursor_t gfb_cursor_shape; 56 static vr_draw_cursor_t gfb_cursor; 57 static vr_blink_cursor_t gfb_blink; 58 #ifndef SC_NO_CUTPASTE 59 static vr_draw_mouse_t gfb_mouse; 60 #else 61 #define gfb_mouse (vr_draw_mouse_t *)gfb_nop 62 #endif 63 64 static void gfb_nop(scr_stat *scp); 65 66 sc_rndr_sw_t txtrndrsw = { 67 (vr_init_t *)gfb_nop, 68 gfb_clear, 69 gfb_border, 70 gfb_draw, 71 gfb_cursor_shape, 72 gfb_cursor, 73 gfb_blink, 74 (vr_set_mouse_t *)gfb_nop, 75 gfb_mouse, 76 }; 77 78 #ifdef SC_PIXEL_MODE 79 sc_rndr_sw_t gfbrndrsw = { 80 (vr_init_t *)gfb_nop, 81 gfb_clear, 82 gfb_border, 83 gfb_draw, 84 gfb_cursor_shape, 85 gfb_cursor, 86 gfb_blink, 87 (vr_set_mouse_t *)gfb_nop, 88 gfb_mouse, 89 }; 90 #endif /* SC_PIXEL_MODE */ 91 92 #ifndef SC_NO_MODE_CHANGE 93 sc_rndr_sw_t grrndrsw = { 94 (vr_init_t *)gfb_nop, 95 (vr_clear_t *)gfb_nop, 96 gfb_border, 97 (vr_draw_t *)gfb_nop, 98 (vr_set_cursor_t *)gfb_nop, 99 (vr_draw_cursor_t *)gfb_nop, 100 (vr_blink_cursor_t *)gfb_nop, 101 (vr_set_mouse_t *)gfb_nop, 102 (vr_draw_mouse_t *)gfb_nop, 103 }; 104 #endif /* SC_NO_MODE_CHANGE */ 105 106 #ifndef SC_NO_CUTPASTE 107 static u_char mouse_pointer[16] = { 108 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68, 109 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 110 }; 111 #endif 112 113 static void 114 gfb_nop(scr_stat *scp) 115 { 116 } 117 118 /* text mode renderer */ 119 120 static void 121 gfb_clear(scr_stat *scp, int c, int attr) 122 { 123 vidd_clear(scp->sc->adp); 124 } 125 126 static void 127 gfb_border(scr_stat *scp, int color) 128 { 129 vidd_set_border(scp->sc->adp, color); 130 } 131 132 static void 133 gfb_draw(scr_stat *scp, int from, int count, int flip) 134 { 135 int c; 136 int a; 137 int i, n; 138 video_adapter_t *adp; 139 140 adp = scp->sc->adp; 141 142 /* 143 Determine if we need to scroll based on the offset 144 and the number of characters to be displayed... 145 */ 146 if (from + count > scp->xsize*scp->ysize) { 147 /* 148 Calculate the number of characters past the end of the 149 visible screen... 150 */ 151 count = (from + count) - 152 (adp->va_info.vi_width * adp->va_info.vi_height); 153 154 /* 155 Calculate the number of rows past the end of the visible 156 screen... 157 */ 158 n = (count / adp->va_info.vi_width) + 1; 159 160 /* Scroll to make room for new text rows... */ 161 vidd_copy(adp, n, 0, n); 162 #if 0 163 vidd_clear(adp, n); 164 #endif 165 166 /* Display new text rows... */ 167 vidd_puts(adp, from, 168 (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), count); 169 } 170 171 /* 172 We don't need to scroll, so we can just put the characters 173 all-at-once... 174 */ 175 else { 176 /* 177 Determine the method by which we are to display characters 178 (are we going to print forwards or backwards? 179 do we need to do a character-by-character copy, then?)... 180 */ 181 if (flip) 182 for (i = count; i-- > 0; ++from) { 183 c = sc_vtb_getc(&scp->vtb, from); 184 a = sc_vtb_geta(&scp->vtb, from) >> 8; 185 vidd_putc(adp, from, c, 186 (a >> 4) | ((a & 0xf) << 4)); 187 } 188 else { 189 vidd_puts(adp, from, 190 (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), 191 count); 192 } 193 } 194 } 195 196 static void 197 gfb_cursor_shape(scr_stat *scp, int base, int height, int blink) 198 { 199 if (base < 0 || base >= scp->font_size) 200 return; 201 /* the caller may set height <= 0 in order to disable the cursor */ 202 #if 0 203 scp->cursor_base = base; 204 scp->cursor_height = height; 205 #endif 206 vidd_set_hw_cursor_shape(scp->sc->adp, base, height, scp->font_size, 207 blink); 208 } 209 210 static int pxlblinkrate = 0; 211 212 #if defined(SC_OFWFB) 213 static void 214 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip) 215 { 216 video_adapter_t *adp; 217 int a, c; 218 219 if (scp->curs_attr.height <= 0) /* the text cursor is disabled */ 220 return; 221 222 adp = scp->sc->adp; 223 if(blink) { 224 scp->status |= VR_CURSOR_BLINK; 225 if (on) { 226 scp->status |= VR_CURSOR_ON; 227 vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize); 228 } else { 229 if (scp->status & VR_CURSOR_ON) 230 vidd_set_hw_cursor(adp, -1, -1); 231 scp->status &= ~VR_CURSOR_ON; 232 } 233 } else { 234 scp->status &= ~VR_CURSOR_BLINK; 235 if(on) { 236 scp->status |= VR_CURSOR_ON; 237 vidd_putc(scp->sc->adp, scp->cursor_oldpos, 238 sc_vtb_getc(&scp->vtb, scp->cursor_oldpos), 239 sc_vtb_geta(&scp->vtb, scp->cursor_oldpos) >> 8); 240 a = sc_vtb_geta(&scp->vtb, at) >> 8; 241 c = sc_vtb_getc(&scp->vtb, at); 242 vidd_putc(scp->sc->adp, at, c, 243 (a >> 4) | ((a & 0xf) << 4)); 244 } else { 245 if (scp->status & VR_CURSOR_ON) 246 vidd_putc(scp->sc->adp, at, 247 sc_vtb_getc(&scp->vtb, at), 248 sc_vtb_geta(&scp->vtb, at) >> 8); 249 scp->status &= ~VR_CURSOR_ON; 250 } 251 } 252 } 253 #else 254 static void 255 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip) 256 { 257 video_adapter_t *adp; 258 259 adp = scp->sc->adp; 260 if (scp->curs_attr.height <= 0) 261 /* the text cursor is disabled */ 262 return; 263 264 if (on) { 265 if (!blink) { 266 scp->status |= VR_CURSOR_ON; 267 vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize); 268 } else if (++pxlblinkrate & 4) { 269 pxlblinkrate = 0; 270 scp->status ^= VR_CURSOR_ON; 271 if(scp->status & VR_CURSOR_ON) 272 vidd_set_hw_cursor(adp, at%scp->xsize, 273 at/scp->xsize); 274 else 275 vidd_set_hw_cursor(adp, -1, -1); 276 } 277 } else { 278 if (scp->status & VR_CURSOR_ON) 279 vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize); 280 scp->status &= ~VR_CURSOR_ON; 281 } 282 if (blink) 283 scp->status |= VR_CURSOR_BLINK; 284 else 285 scp->status &= ~VR_CURSOR_BLINK; 286 } 287 #endif 288 289 static void 290 gfb_blink(scr_stat *scp, int at, int flip) 291 { 292 if (!(scp->status & VR_CURSOR_BLINK)) 293 return; 294 if (!(++pxlblinkrate & 4)) 295 return; 296 pxlblinkrate = 0; 297 scp->status ^= VR_CURSOR_ON; 298 gfb_cursor(scp, at, scp->status & VR_CURSOR_BLINK, 299 scp->status & VR_CURSOR_ON, flip); 300 } 301 302 #ifndef SC_NO_CUTPASTE 303 304 static void 305 gfb_mouse(scr_stat *scp, int x, int y, int on) 306 { 307 if (on) { 308 vidd_putm(scp->sc->adp, x, y, mouse_pointer, 309 0xffffffff, 16, 8); 310 } else { 311 /* XXX: removal is incomplete for h/w cursors and borders. */ 312 } 313 } 314 315 #endif /* SC_NO_CUTPASTE */ 316