]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/dev/syscons/scgfbrndr.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / dev / syscons / scgfbrndr.c
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
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include "opt_syscons.h"
33 #include "opt_gfb.h"
34 #ifdef __powerpc__
35 #include "opt_ofwfb.h"
36 #endif
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/fbio.h>
42 #include <sys/consio.h>
43
44 #include <machine/bus.h>
45
46 #include <dev/fb/fbreg.h>
47 #include <dev/syscons/syscons.h>
48
49 #ifndef SC_RENDER_DEBUG
50 #define SC_RENDER_DEBUG         0
51 #endif
52
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;
61 #else
62 #define gfb_mouse               (vr_draw_mouse_t *)gfb_nop
63 #endif
64
65 static void                     gfb_nop(scr_stat *scp);
66
67 sc_rndr_sw_t txtrndrsw = {
68         (vr_init_t *)gfb_nop,
69         gfb_clear,
70         gfb_border,
71         gfb_draw,       
72         gfb_cursor_shape,
73         gfb_cursor,
74         gfb_blink,
75         (vr_set_mouse_t *)gfb_nop,
76         gfb_mouse,
77 };
78
79 #ifdef SC_PIXEL_MODE
80 sc_rndr_sw_t gfbrndrsw = {
81         (vr_init_t *)gfb_nop,
82         gfb_clear,
83         gfb_border,
84         gfb_draw,
85         gfb_cursor_shape,
86         gfb_cursor,
87         gfb_blink,
88         (vr_set_mouse_t *)gfb_nop,
89         gfb_mouse,
90 };
91 #endif /* SC_PIXEL_MODE */
92
93 #ifndef SC_NO_MODE_CHANGE
94 sc_rndr_sw_t grrndrsw = {
95         (vr_init_t *)gfb_nop,
96         (vr_clear_t *)gfb_nop,
97         gfb_border,
98         (vr_draw_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,
104 };
105 #endif /* SC_NO_MODE_CHANGE */
106
107 #ifndef SC_NO_CUTPASTE
108 #ifdef __sparc64__
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      /* ............ */
132 };
133 #else
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
137 };
138 #endif
139 #endif
140
141 static void
142 gfb_nop(scr_stat *scp)
143 {
144 }
145
146 /* text mode renderer */
147
148 static void
149 gfb_clear(scr_stat *scp, int c, int attr)
150 {
151         vidd_clear(scp->sc->adp);
152 }
153
154 static void
155 gfb_border(scr_stat *scp, int color)
156 {
157         vidd_set_border(scp->sc->adp, color);
158 }
159
160 static void
161 gfb_draw(scr_stat *scp, int from, int count, int flip)
162 {
163         int c;
164         int a;
165         int i, n;
166         video_adapter_t *adp;
167
168         adp = scp->sc->adp;
169
170         /*
171            Determine if we need to scroll based on the offset
172            and the number of characters to be displayed...
173          */
174         if (from + count > scp->xsize*scp->ysize) {
175
176                 /*
177                    Calculate the number of characters past the end of the
178                    visible screen...
179                 */
180                 count = (from + count) -
181                     (adp->va_info.vi_width * adp->va_info.vi_height);
182
183                 /*
184                    Calculate the number of rows past the end of the visible
185                    screen...
186                 */
187                 n = (count / adp->va_info.vi_width) + 1;
188
189                 /* Scroll to make room for new text rows... */
190                 vidd_copy(adp, n, 0, n);
191 #if 0
192                 vidd_clear(adp, n);
193 #endif
194
195                 /* Display new text rows... */
196                 vidd_puts(adp, from,
197                     (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), count);
198         }
199
200         /*
201            We don't need to scroll, so we can just put the characters
202            all-at-once...
203         */
204         else {
205
206                 /*
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?)...
210                 */
211                 if (flip)
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));
217                         }
218                 else {
219                         vidd_puts(adp, from,
220                             (u_int16_t *)sc_vtb_pointer(&scp->vtb, from),
221                             count);
222                 }
223         }
224 }
225
226 static void 
227 gfb_cursor_shape(scr_stat *scp, int base, int height, int blink)
228 {
229         if (base < 0 || base >= scp->font_size)
230                 return;
231         /* the caller may set height <= 0 in order to disable the cursor */
232 #if 0
233         scp->cursor_base = base;
234         scp->cursor_height = height;
235 #endif
236         vidd_set_hw_cursor_shape(scp->sc->adp, base, height, scp->font_size,
237             blink);
238 }
239
240 static int pxlblinkrate = 0;
241
242 #if defined(__sparc64__) || defined(SC_OFWFB)
243 static void
244 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
245 {
246         video_adapter_t *adp;
247         int a, c;
248
249         if (scp->curs_attr.height <= 0) /* the text cursor is disabled */
250                 return;
251
252         adp = scp->sc->adp;
253         if(blink) {
254                 scp->status |= VR_CURSOR_BLINK;
255                 if (on) {
256                         scp->status |= VR_CURSOR_ON;
257                         vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
258                 } else {
259                         if (scp->status & VR_CURSOR_ON)
260                                 vidd_set_hw_cursor(adp, -1, -1);
261                         scp->status &= ~VR_CURSOR_ON;
262                 }
263         } else {
264                 scp->status &= ~VR_CURSOR_BLINK;
265                 if(on) {
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;
276                 } else {
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;
282                 }
283         }
284 }
285 #else
286 static void 
287 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
288 {
289         video_adapter_t *adp;
290
291         adp = scp->sc->adp;
292         if (scp->curs_attr.height <= 0) 
293                 /* the text cursor is disabled */
294                 return;
295
296         if (on) {
297                 if (!blink) {
298                         scp->status |= VR_CURSOR_ON;
299                         vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
300                 } else if (++pxlblinkrate & 4) {
301                         pxlblinkrate = 0;
302                         scp->status ^= VR_CURSOR_ON;
303                         if(scp->status & VR_CURSOR_ON)
304                                 vidd_set_hw_cursor(adp, at%scp->xsize,
305                                     at/scp->xsize);
306                         else
307                                 vidd_set_hw_cursor(adp, -1, -1);
308                 }
309         } else {
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;
313         }
314         if (blink)
315                 scp->status |= VR_CURSOR_BLINK;
316         else
317                 scp->status &= ~VR_CURSOR_BLINK;
318 }
319 #endif
320
321 static void
322 gfb_blink(scr_stat *scp, int at, int flip)
323 {
324         if (!(scp->status & VR_CURSOR_BLINK))
325                 return;
326         if (!(++pxlblinkrate & 4))
327                 return;
328         pxlblinkrate = 0;
329         scp->status ^= VR_CURSOR_ON;
330         gfb_cursor(scp, at, scp->status & VR_CURSOR_BLINK,
331             scp->status & VR_CURSOR_ON, flip);
332 }
333
334 #ifndef SC_NO_CUTPASTE
335
336 static void 
337 gfb_mouse(scr_stat *scp, int x, int y, int on)
338 {
339 #ifdef __sparc64__
340                 vidd_putm(scp->sc->adp, x, y, mouse_pointer,
341                     on ? 0xffffffff : 0x0, 22, 12);
342 #else
343         int i, pos;
344
345         if (on) {
346
347                 /* Display the mouse pointer image... */
348                 vidd_putm(scp->sc->adp, x, y, mouse_pointer,
349                     0xffffffff, 16, 8);
350         } else {
351
352                 /*
353                    Erase the mouse cursor image by redrawing the text
354                    underneath it...
355                 */
356                 return;
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);
362         }
363 #endif
364 }
365
366 #endif /* SC_NO_CUTPASTE */