syscons(4): Base renderer selection on the new mode's memory model.
[dragonfly.git] / sys / dev / misc / syscons / scgfbrndr.c
CommitLineData
984263bc
MD
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
1de703da
MD
27 *
28 * $FreeBSD: src/sys/dev/syscons/scgfbrndr.c,v 1.14.2.1 2001/11/01 08:33:15 obrien Exp $
1f7ab7c9 29 * $DragonFly: src/sys/dev/misc/syscons/scgfbrndr.c,v 1.6 2006/10/25 20:55:55 dillon Exp $
984263bc
MD
30 */
31
984263bc
MD
32#include "opt_syscons.h"
33#include "opt_gfb.h"
34
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>
1f7ab7c9 40#include <sys/bus.h>
984263bc
MD
41
42#include <dev/fb/fbreg.h>
1f2de5d4 43#include "syscons.h"
984263bc 44
984263bc
MD
45static vr_clear_t gfb_clear;
46static vr_draw_border_t gfb_border;
47static vr_draw_t gfb_draw;
48static vr_set_cursor_t gfb_cursor_shape;
49static vr_draw_cursor_t gfb_cursor;
50static vr_blink_cursor_t gfb_blink;
51#ifndef SC_NO_CUTPASTE
52static vr_draw_mouse_t gfb_mouse;
53#else
54#define gfb_mouse (vr_draw_mouse_t *)gfb_nop
55#endif
56
57static void gfb_nop(scr_stat *scp, ...);
58
59sc_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,
68};
69
70#ifdef SC_PIXEL_MODE
71sc_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,
80};
81#endif /* SC_PIXEL_MODE */
82
83#ifndef SC_NO_MODE_CHANGE
84sc_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,
93};
94#endif /* SC_NO_MODE_CHANGE */
95
96#ifndef SC_NO_CUTPASTE
97
98static u_char mouse_pointer[16] = {
99 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68,
100 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
101};
102#endif
103
104static void
105gfb_nop(scr_stat *scp, ...)
106{
107}
108
109/* text mode renderer */
110
111static void
112gfb_clear(scr_stat *scp, int c, int attr)
113{
114 (*vidsw[scp->sc->adapter]->clear)(scp->sc->adp);
115}
116
117static void
118gfb_border(scr_stat *scp, int color)
119{
120 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
121}
122
123static void
124gfb_draw(scr_stat *scp, int from, int count, int flip)
125{
126 char c;
127 char a;
128 int i, n;
129 video_adapter_t *adp;
130
131 adp = scp->sc->adp;
132
133 /*
134 Determine if we need to scroll based on the offset
135 and the number of characters to be displayed...
136 */
137 if (from + count > scp->xsize*scp->ysize) {
138
139 /*
140 Calculate the number of characters past the end of the
141 visible screen...
142 */
143 count = (from + count) -
144 (adp->va_info.vi_width * adp->va_info.vi_height);
145
146 /*
147 Calculate the number of rows past the end of the visible
148 screen...
149 */
150 n = (count / adp->va_info.vi_width) + 1;
151
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
157
158 /* Display new text rows... */
159 (*vidsw[scp->sc->adapter]->puts)(adp, from,
47d95543 160 scp->vtb.vtb_buffer + from, count);
984263bc
MD
161 }
162
163 /*
164 We don't need to scroll, so we can just put the characters
165 all-at-once...
166 */
167 else {
168
169 /*
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?)...
173 */
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,
179 a);
180 }
181 else {
182 (*vidsw[scp->sc->adapter]->puts)(adp, from,
47d95543 183 scp->vtb.vtb_buffer + from, count);
984263bc
MD
184 }
185 }
186}
187
188static void
189gfb_cursor_shape(scr_stat *scp, int base, int height, int blink)
190{
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);
200}
201
202static int pxlblinkrate = 0;
203
204#ifdef 0
205static void
206gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
207{
208 video_adapter_t *adp;
209
210 if (scp->cursor_height <= 0) /* the text cursor is disabled */
211 return;
212
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;
226 }
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;
242 }
243 }
244}
245#endif
246
247static void
248gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
249{
250 video_adapter_t *adp;
251
252 adp = scp->sc->adp;
253 if (scp->cursor_height <= 0) /* the text cursor is disabled */
254 return;
255
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);
270 }
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;
276 }
277 if (blink)
278 scp->status |= VR_CURSOR_BLINK;
279 else
280 scp->status &= ~VR_CURSOR_BLINK;
281}
282
283static void
284gfb_blink(scr_stat *scp, int at, int flip)
285{
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);
294}
295
296#ifndef SC_NO_CUTPASTE
297
298static void
299gfb_mouse(scr_stat *scp, int x, int y, int on)
300{
301 int i, pos;
302
303 if (on) {
304
305 /* Display the mouse pointer image... */
306 (*vidsw[scp->sc->adapter]->putm)(scp->sc->adp, x, y,
307 mouse_pointer, 0xffffffff, 16);
308 } else {
309
310 /*
311 Erase the mouse cursor image by redrawing the text
312 underneath it...
313 */
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);
320 }
321}
322
323#endif /* SC_NO_CUTPASTE */