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