2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
26 * Copyright (c) 2000 Andrew Miklic
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include "opt_syscons.h"
35 #include "opt_ofwfb.h"
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
42 #include <sys/consio.h>
44 #include <machine/bus.h>
46 #include <dev/fb/fbreg.h>
47 #include <dev/syscons/syscons.h>
49 #ifndef SC_RENDER_DEBUG
50 #define SC_RENDER_DEBUG 0
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;
62 #define gfb_mouse (vr_draw_mouse_t *)gfb_nop
65 static void gfb_nop(scr_stat *scp);
67 sc_rndr_sw_t txtrndrsw = {
75 (vr_set_mouse_t *)gfb_nop,
80 sc_rndr_sw_t gfbrndrsw = {
88 (vr_set_mouse_t *)gfb_nop,
91 #endif /* SC_PIXEL_MODE */
93 #ifndef SC_NO_MODE_CHANGE
94 sc_rndr_sw_t grrndrsw = {
96 (vr_clear_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,
105 #endif /* SC_NO_MODE_CHANGE */
107 #ifndef SC_NO_CUTPASTE
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 /* ............ */
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
142 gfb_nop(scr_stat *scp)
146 /* text mode renderer */
149 gfb_clear(scr_stat *scp, int c, int attr)
151 vidd_clear(scp->sc->adp);
155 gfb_border(scr_stat *scp, int color)
157 vidd_set_border(scp->sc->adp, color);
161 gfb_draw(scr_stat *scp, int from, int count, int flip)
166 video_adapter_t *adp;
171 Determine if we need to scroll based on the offset
172 and the number of characters to be displayed...
174 if (from + count > scp->xsize*scp->ysize) {
177 Calculate the number of characters past the end of the
180 count = (from + count) -
181 (adp->va_info.vi_width * adp->va_info.vi_height);
184 Calculate the number of rows past the end of the visible
187 n = (count / adp->va_info.vi_width) + 1;
189 /* Scroll to make room for new text rows... */
190 vidd_copy(adp, n, 0, n);
195 /* Display new text rows... */
197 (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), count);
201 We don't need to scroll, so we can just put the characters
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?)...
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));
220 (u_int16_t *)sc_vtb_pointer(&scp->vtb, from),
227 gfb_cursor_shape(scr_stat *scp, int base, int height, int blink)
229 if (base < 0 || base >= scp->font_size)
231 /* the caller may set height <= 0 in order to disable the cursor */
233 scp->cursor_base = base;
234 scp->cursor_height = height;
236 vidd_set_hw_cursor_shape(scp->sc->adp, base, height, scp->font_size,
240 static int pxlblinkrate = 0;
242 #if defined(__sparc64__) || defined(SC_OFWFB)
244 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
246 video_adapter_t *adp;
249 if (scp->curs_attr.height <= 0) /* the text cursor is disabled */
254 scp->status |= VR_CURSOR_BLINK;
256 scp->status |= VR_CURSOR_ON;
257 vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
259 if (scp->status & VR_CURSOR_ON)
260 vidd_set_hw_cursor(adp, -1, -1);
261 scp->status &= ~VR_CURSOR_ON;
264 scp->status &= ~VR_CURSOR_BLINK;
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 scp->cursor_saveunder_attr = a;
275 scp->cursor_saveunder_char = c;
277 if (scp->status & VR_CURSOR_ON)
278 vidd_putc(scp->sc->adp, at,
279 scp->cursor_saveunder_char,
280 scp->cursor_saveunder_attr);
281 scp->status &= ~VR_CURSOR_ON;
287 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
289 video_adapter_t *adp;
292 if (scp->curs_attr.height <= 0)
293 /* the text cursor is disabled */
298 scp->status |= VR_CURSOR_ON;
299 vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
300 } else if (++pxlblinkrate & 4) {
302 scp->status ^= VR_CURSOR_ON;
303 if(scp->status & VR_CURSOR_ON)
304 vidd_set_hw_cursor(adp, at%scp->xsize,
307 vidd_set_hw_cursor(adp, -1, -1);
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;
315 scp->status |= VR_CURSOR_BLINK;
317 scp->status &= ~VR_CURSOR_BLINK;
322 gfb_blink(scr_stat *scp, int at, int flip)
324 if (!(scp->status & VR_CURSOR_BLINK))
326 if (!(++pxlblinkrate & 4))
329 scp->status ^= VR_CURSOR_ON;
330 gfb_cursor(scp, at, scp->status & VR_CURSOR_BLINK,
331 scp->status & VR_CURSOR_ON, flip);
334 #ifndef SC_NO_CUTPASTE
337 gfb_mouse(scr_stat *scp, int x, int y, int on)
340 vidd_putm(scp->sc->adp, x, y, mouse_pointer,
341 on ? 0xffffffff : 0x0, 22, 12);
347 /* Display the mouse pointer image... */
348 vidd_putm(scp->sc->adp, x, y, mouse_pointer,
353 Erase the mouse cursor image by redrawing the text
357 pos = x*scp->xsize + y;
358 i = (y < scp->xsize - 1) ? 2 : 1;
359 (*scp->rndr->draw)(scp, pos, i, FALSE);
360 if (x < scp->ysize - 1)
361 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
366 #endif /* SC_NO_CUTPASTE */