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