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 (*vidsw[scp->sc->adapter]->clear)(scp->sc->adp);
155 gfb_border(scr_stat *scp, int color)
157 (*vidsw[scp->sc->adapter]->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 (*vidsw[scp->sc->adapter]->copy)(adp, n, 0, n);
192 (*vidsw[scp->sc->adapter]->clear)(adp, n);
195 /* Display new text rows... */
196 (*vidsw[scp->sc->adapter]->puts)(adp, from,
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 (*vidsw[scp->sc->adapter]->putc)(adp, from, c,
216 (a >> 4) | ((a & 0xf) << 4));
219 (*vidsw[scp->sc->adapter]->puts)(adp, from,
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 (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
237 base, height, scp->font_size, blink);
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 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
261 if (scp->status & VR_CURSOR_ON)
262 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1,
264 scp->status &= ~VR_CURSOR_ON;
267 scp->status &= ~VR_CURSOR_BLINK;
269 scp->status |= VR_CURSOR_ON;
270 (*vidsw[scp->sc->adapter]->putc)(scp->sc->adp,
272 sc_vtb_getc(&scp->vtb, scp->cursor_oldpos),
273 sc_vtb_geta(&scp->vtb, scp->cursor_oldpos) >> 8);
274 a = sc_vtb_geta(&scp->vtb, at) >> 8;
275 c = sc_vtb_getc(&scp->vtb, at);
276 (*vidsw[scp->sc->adapter]->putc)(scp->sc->adp, at,
277 c, (a >> 4) | ((a & 0xf) << 4));
278 scp->cursor_saveunder_attr = a;
279 scp->cursor_saveunder_char = c;
281 if (scp->status & VR_CURSOR_ON)
282 (*vidsw[scp->sc->adapter]->putc)(scp->sc->adp,
283 at, scp->cursor_saveunder_char,
284 scp->cursor_saveunder_attr);
285 scp->status &= ~VR_CURSOR_ON;
291 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
293 video_adapter_t *adp;
296 if (scp->curs_attr.height <= 0)
297 /* the text cursor is disabled */
302 scp->status |= VR_CURSOR_ON;
303 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
304 at%scp->xsize, at/scp->xsize);
305 } else if (++pxlblinkrate & 4) {
307 scp->status ^= VR_CURSOR_ON;
308 if(scp->status & VR_CURSOR_ON)
309 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
310 at%scp->xsize, at/scp->xsize);
312 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1,
316 if (scp->status & VR_CURSOR_ON)
317 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
318 at%scp->xsize, at/scp->xsize);
319 scp->status &= ~VR_CURSOR_ON;
322 scp->status |= VR_CURSOR_BLINK;
324 scp->status &= ~VR_CURSOR_BLINK;
329 gfb_blink(scr_stat *scp, int at, int flip)
331 if (!(scp->status & VR_CURSOR_BLINK))
333 if (!(++pxlblinkrate & 4))
336 scp->status ^= VR_CURSOR_ON;
337 gfb_cursor(scp, at, scp->status & VR_CURSOR_BLINK,
338 scp->status & VR_CURSOR_ON, flip);
341 #ifndef SC_NO_CUTPASTE
344 gfb_mouse(scr_stat *scp, int x, int y, int on)
347 (*vidsw[scp->sc->adapter]->putm)(scp->sc->adp, x, y,
348 mouse_pointer, on ? 0xffffffff : 0x0, 22, 12);
354 /* Display the mouse pointer image... */
355 (*vidsw[scp->sc->adapter]->putm)(scp->sc->adp, x, y,
356 mouse_pointer, 0xffffffff, 16, 8);
360 Erase the mouse cursor image by redrawing the text
364 pos = x*scp->xsize + y;
365 i = (y < scp->xsize - 1) ? 2 : 1;
366 (*scp->rndr->draw)(scp, pos, i, FALSE);
367 if (x < scp->ysize - 1)
368 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
373 #endif /* SC_NO_CUTPASTE */