2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer as
12 * the first lines of this file unmodified.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Copyright (c) 2000 Andrew Miklic
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include "opt_syscons.h"
37 #include "opt_ofwfb.h"
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
44 #include <sys/consio.h>
46 #include <machine/bus.h>
48 #include <dev/fb/fbreg.h>
49 #include <dev/syscons/syscons.h>
51 #ifndef SC_RENDER_DEBUG
52 #define SC_RENDER_DEBUG 0
55 static vr_clear_t gfb_clear;
56 static vr_draw_border_t gfb_border;
57 static vr_draw_t gfb_draw;
58 static vr_set_cursor_t gfb_cursor_shape;
59 static vr_draw_cursor_t gfb_cursor;
60 static vr_blink_cursor_t gfb_blink;
61 #ifndef SC_NO_CUTPASTE
62 static vr_draw_mouse_t gfb_mouse;
64 #define gfb_mouse (vr_draw_mouse_t *)gfb_nop
67 static void gfb_nop(scr_stat *scp);
69 sc_rndr_sw_t txtrndrsw = {
77 (vr_set_mouse_t *)gfb_nop,
82 sc_rndr_sw_t gfbrndrsw = {
90 (vr_set_mouse_t *)gfb_nop,
93 #endif /* SC_PIXEL_MODE */
95 #ifndef SC_NO_MODE_CHANGE
96 sc_rndr_sw_t grrndrsw = {
98 (vr_clear_t *)gfb_nop,
100 (vr_draw_t *)gfb_nop,
101 (vr_set_cursor_t *)gfb_nop,
102 (vr_draw_cursor_t *)gfb_nop,
103 (vr_blink_cursor_t *)gfb_nop,
104 (vr_set_mouse_t *)gfb_nop,
105 (vr_draw_mouse_t *)gfb_nop,
107 #endif /* SC_NO_MODE_CHANGE */
109 #ifndef SC_NO_CUTPASTE
111 static u_char mouse_pointer[22 * 2] = {
112 0x00, 0x00, /* ............ */
113 0x80, 0x00, /* *........... */
114 0xc0, 0x00, /* **.......... */
115 0xe0, 0x00, /* ***......... */
116 0xf0, 0x00, /* ****........ */
117 0xf8, 0x00, /* *****....... */
118 0xfc, 0x00, /* ******...... */
119 0xfe, 0x00, /* *******..... */
120 0xff, 0x00, /* ********.... */
121 0xff, 0x80, /* *********... */
122 0xfc, 0xc0, /* ******..**.. */
123 0xdc, 0x00, /* **.***...... */
124 0x8e, 0x00, /* *...***..... */
125 0x0e, 0x00, /* ....***..... */
126 0x07, 0x00, /* .....***.... */
127 0x04, 0x00, /* .....*...... */
128 0x00, 0x00, /* ............ */
129 0x00, 0x00, /* ............ */
130 0x00, 0x00, /* ............ */
131 0x00, 0x00, /* ............ */
132 0x00, 0x00, /* ............ */
133 0x00, 0x00 /* ............ */
136 static u_char mouse_pointer[16] = {
137 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68,
138 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
144 gfb_nop(scr_stat *scp)
148 /* text mode renderer */
151 gfb_clear(scr_stat *scp, int c, int attr)
153 vidd_clear(scp->sc->adp);
157 gfb_border(scr_stat *scp, int color)
159 vidd_set_border(scp->sc->adp, color);
163 gfb_draw(scr_stat *scp, int from, int count, int flip)
168 video_adapter_t *adp;
173 Determine if we need to scroll based on the offset
174 and the number of characters to be displayed...
176 if (from + count > scp->xsize*scp->ysize) {
179 Calculate the number of characters past the end of the
182 count = (from + count) -
183 (adp->va_info.vi_width * adp->va_info.vi_height);
186 Calculate the number of rows past the end of the visible
189 n = (count / adp->va_info.vi_width) + 1;
191 /* Scroll to make room for new text rows... */
192 vidd_copy(adp, n, 0, n);
197 /* Display new text rows... */
199 (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), count);
203 We don't need to scroll, so we can just put the characters
209 Determine the method by which we are to display characters
210 (are we going to print forwards or backwards?
211 do we need to do a character-by-character copy, then?)...
214 for (i = count; i-- > 0; ++from) {
215 c = sc_vtb_getc(&scp->vtb, from);
216 a = sc_vtb_geta(&scp->vtb, from) >> 8;
217 vidd_putc(adp, from, c,
218 (a >> 4) | ((a & 0xf) << 4));
222 (u_int16_t *)sc_vtb_pointer(&scp->vtb, from),
229 gfb_cursor_shape(scr_stat *scp, int base, int height, int blink)
231 if (base < 0 || base >= scp->font_size)
233 /* the caller may set height <= 0 in order to disable the cursor */
235 scp->cursor_base = base;
236 scp->cursor_height = height;
238 vidd_set_hw_cursor_shape(scp->sc->adp, base, height, scp->font_size,
242 static int pxlblinkrate = 0;
244 #if defined(__sparc64__) || defined(SC_OFWFB)
246 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
248 video_adapter_t *adp;
251 if (scp->curs_attr.height <= 0) /* the text cursor is disabled */
256 scp->status |= VR_CURSOR_BLINK;
258 scp->status |= VR_CURSOR_ON;
259 vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
261 if (scp->status & VR_CURSOR_ON)
262 vidd_set_hw_cursor(adp, -1, -1);
263 scp->status &= ~VR_CURSOR_ON;
266 scp->status &= ~VR_CURSOR_BLINK;
268 scp->status |= VR_CURSOR_ON;
269 vidd_putc(scp->sc->adp, scp->cursor_oldpos,
270 sc_vtb_getc(&scp->vtb, scp->cursor_oldpos),
271 sc_vtb_geta(&scp->vtb, scp->cursor_oldpos) >> 8);
272 a = sc_vtb_geta(&scp->vtb, at) >> 8;
273 c = sc_vtb_getc(&scp->vtb, at);
274 vidd_putc(scp->sc->adp, at, c,
275 (a >> 4) | ((a & 0xf) << 4));
277 if (scp->status & VR_CURSOR_ON)
278 vidd_putc(scp->sc->adp, at,
279 sc_vtb_getc(&scp->vtb, at),
280 sc_vtb_geta(&scp->vtb, at) >> 8);
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);
344 vidd_putm(scp->sc->adp, x, y, mouse_pointer,
347 /* XXX: removal is incomplete for h/w cursors and borders. */
352 #endif /* SC_NO_CUTPASTE */