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