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