More minor IPI work.
[dragonfly/vkernel-mp.git] / sys / dev / misc / syscons / scgfbrndr.c
blob11f5c72274d061ea5197badc2dc2a4c0b439f927
1 /*-
2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3 * All rights reserved.
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.
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
28 * $FreeBSD: src/sys/dev/syscons/scgfbrndr.c,v 1.14.2.1 2001/11/01 08:33:15 obrien Exp $
29 * $DragonFly: src/sys/dev/misc/syscons/scgfbrndr.c,v 1.6 2006/10/25 22:55:55 dillon Exp $
32 #include "opt_syscons.h"
33 #include "opt_gfb.h"
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 #include <sys/bus.h>
42 #include <dev/fb/fbreg.h>
43 #include "syscons.h"
45 static vr_clear_t gfb_clear;
46 static vr_draw_border_t gfb_border;
47 static vr_draw_t gfb_draw;
48 static vr_set_cursor_t gfb_cursor_shape;
49 static vr_draw_cursor_t gfb_cursor;
50 static vr_blink_cursor_t gfb_blink;
51 #ifndef SC_NO_CUTPASTE
52 static vr_draw_mouse_t gfb_mouse;
53 #else
54 #define gfb_mouse (vr_draw_mouse_t *)gfb_nop
55 #endif
57 static void gfb_nop(scr_stat *scp, ...);
59 sc_rndr_sw_t txtrndrsw = {
60 gfb_clear,
61 gfb_border,
62 gfb_draw,
63 gfb_cursor_shape,
64 gfb_cursor,
65 gfb_blink,
66 (vr_set_mouse_t *)gfb_nop,
67 gfb_mouse,
70 #ifdef SC_PIXEL_MODE
71 sc_rndr_sw_t gfbrndrsw = {
72 gfb_clear,
73 gfb_border,
74 gfb_draw,
75 gfb_cursor_shape,
76 gfb_cursor,
77 gfb_blink,
78 (vr_set_mouse_t *)gfb_nop,
79 gfb_mouse,
81 #endif /* SC_PIXEL_MODE */
83 #ifndef SC_NO_MODE_CHANGE
84 sc_rndr_sw_t grrndrsw = {
85 (vr_clear_t *)gfb_nop,
86 gfb_border,
87 (vr_draw_t *)gfb_nop,
88 (vr_set_cursor_t *)gfb_nop,
89 (vr_draw_cursor_t *)gfb_nop,
90 (vr_blink_cursor_t *)gfb_nop,
91 (vr_set_mouse_t *)gfb_nop,
92 (vr_draw_mouse_t *)gfb_nop,
94 #endif /* SC_NO_MODE_CHANGE */
96 #ifndef SC_NO_CUTPASTE
98 static u_char mouse_pointer[16] = {
99 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68,
100 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
102 #endif
104 static void
105 gfb_nop(scr_stat *scp, ...)
109 /* text mode renderer */
111 static void
112 gfb_clear(scr_stat *scp, int c, int attr)
114 (*vidsw[scp->sc->adapter]->clear)(scp->sc->adp);
117 static void
118 gfb_border(scr_stat *scp, int color)
120 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
123 static void
124 gfb_draw(scr_stat *scp, int from, int count, int flip)
126 char c;
127 char a;
128 int i, n;
129 video_adapter_t *adp;
131 adp = scp->sc->adp;
134 Determine if we need to scroll based on the offset
135 and the number of characters to be displayed...
137 if (from + count > scp->xsize*scp->ysize) {
140 Calculate the number of characters past the end of the
141 visible screen...
143 count = (from + count) -
144 (adp->va_info.vi_width * adp->va_info.vi_height);
147 Calculate the number of rows past the end of the visible
148 screen...
150 n = (count / adp->va_info.vi_width) + 1;
152 /* Scroll to make room for new text rows... */
153 (*vidsw[scp->sc->adapter]->copy)(adp, n, 0, n);
154 #ifdef 0
155 (*vidsw[scp->sc->adapter]->clear)(adp, n);
156 #endif
158 /* Display new text rows... */
159 (*vidsw[scp->sc->adapter]->puts)(adp, from,
160 scp->vtb.vtb_buffer + from, count);
164 We don't need to scroll, so we can just put the characters
165 all-at-once...
167 else {
170 Determine the method by which we are to display characters
171 (are we going to print forwards or backwards?
172 do we need to do a character-by-character copy, then?)...
174 if (flip)
175 for (i = count; i-- > 0; ++from) {
176 c = sc_vtb_getc(&scp->vtb, from);
177 a = sc_vtb_geta(&scp->vtb, from) >> 8;
178 (*vidsw[scp->sc->adapter]->putc)(adp, from, c,
181 else {
182 (*vidsw[scp->sc->adapter]->puts)(adp, from,
183 scp->vtb.vtb_buffer + from, count);
188 static void
189 gfb_cursor_shape(scr_stat *scp, int base, int height, int blink)
191 if (base < 0 || base >= scp->font_size)
192 return;
193 /* the caller may set height <= 0 in order to disable the cursor */
194 #if 0
195 scp->cursor_base = base;
196 scp->cursor_height = height;
197 #endif
198 (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
199 base, height, scp->font_size, blink);
202 static int pxlblinkrate = 0;
204 #ifdef 0
205 static void
206 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
208 video_adapter_t *adp;
210 if (scp->cursor_height <= 0) /* the text cursor is disabled */
211 return;
213 adp = scp->sc->adp;
214 if(blink) {
215 scp->status |= VR_CURSOR_BLINK;
216 if (on) {
217 scp->status |= VR_CURSOR_ON;
218 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
219 at%scp->xsize,
220 at/scp->xsize);
221 } else {
222 if (scp->status & VR_CURSOR_ON)
223 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1,
224 -1);
225 scp->status &= ~VR_CURSOR_ON;
227 } else {
228 scp->status &= ~VR_CURSOR_BLINK;
229 if(on) {
230 scp->status |= VR_CURSOR_ON;
231 scp->cursor_saveunder_char = sc_vtb_getc(&scp->scr, at);
232 scp->cursor_saveunder_attr = sc_vtb_geta(&scp->scr, at);
233 (*vidsw[scp->sc->adapter]->putc)(scp->sc->adp, at,
234 scp->cursor_saveunder_char,
235 scp->cursor_saveunder_attr);
236 } else {
237 if (scp->status & VR_CURSOR_ON)
238 (*vidsw[scp->sc->adapter]->putc)(scp->sc->adp,
239 at, scp->cursor_saveunder_char,
240 scp->cursor_saveunder_attr);
241 scp->status &= ~VR_CURSOR_ON;
245 #endif
247 static void
248 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
250 video_adapter_t *adp;
252 adp = scp->sc->adp;
253 if (scp->cursor_height <= 0) /* the text cursor is disabled */
254 return;
256 if (on) {
257 if (!blink) {
258 scp->status |= VR_CURSOR_ON;
259 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
260 at%scp->xsize, at/scp->xsize);
261 } else if (++pxlblinkrate & 4) {
262 pxlblinkrate = 0;
263 scp->status ^= VR_CURSOR_ON;
264 if(scp->status & VR_CURSOR_ON)
265 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
266 at%scp->xsize, at/scp->xsize);
267 else
268 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1,
269 -1);
271 } else {
272 if (scp->status & VR_CURSOR_ON)
273 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
274 at%scp->xsize, at/scp->xsize);
275 scp->status &= ~VR_CURSOR_ON;
277 if (blink)
278 scp->status |= VR_CURSOR_BLINK;
279 else
280 scp->status &= ~VR_CURSOR_BLINK;
283 static void
284 gfb_blink(scr_stat *scp, int at, int flip)
286 if (!(scp->status & VR_CURSOR_BLINK))
287 return;
288 if (!(++pxlblinkrate & 4))
289 return;
290 pxlblinkrate = 0;
291 scp->status ^= VR_CURSOR_ON;
292 gfb_cursor(scp, at, scp->status & VR_CURSOR_BLINK,
293 scp->status & VR_CURSOR_ON, flip);
296 #ifndef SC_NO_CUTPASTE
298 static void
299 gfb_mouse(scr_stat *scp, int x, int y, int on)
301 int i, pos;
303 if (on) {
305 /* Display the mouse pointer image... */
306 (*vidsw[scp->sc->adapter]->putm)(scp->sc->adp, x, y,
307 mouse_pointer, 0xffffffff, 16);
308 } else {
311 Erase the mouse cursor image by redrawing the text
312 underneath it...
314 return;
315 pos = x*scp->xsize + y;
316 i = (y < scp->xsize - 1) ? 2 : 1;
317 (*scp->rndr->draw)(scp, pos, i, FALSE);
318 if (x < scp->ysize - 1)
319 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
323 #endif /* SC_NO_CUTPASTE */