]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/syscons/scgfbrndr.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.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         (*vidsw[scp->sc->adapter]->clear)(scp->sc->adp);
152 }
153
154 static void
155 gfb_border(scr_stat *scp, int color)
156 {
157         (*vidsw[scp->sc->adapter]->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                 (*vidsw[scp->sc->adapter]->copy)(adp, n, 0, n);
191 #if 0
192                 (*vidsw[scp->sc->adapter]->clear)(adp, n);
193 #endif
194
195                 /* Display new text rows... */
196                 (*vidsw[scp->sc->adapter]->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                                 (*vidsw[scp->sc->adapter]->putc)(adp, from, c,
216                                     (a >> 4) | ((a & 0xf) << 4));
217                         }
218                 else {
219                         (*vidsw[scp->sc->adapter]->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         (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
237             base, height, scp->font_size, 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                         (*vidsw[adp->va_index]->set_hw_cursor)(adp,
258                             at%scp->xsize,
259                             at/scp->xsize);
260                 } else {
261                         if (scp->status & VR_CURSOR_ON)
262                                 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1,
263                                     -1);
264                         scp->status &= ~VR_CURSOR_ON;
265                 }
266         } else {
267                 scp->status &= ~VR_CURSOR_BLINK;
268                 if(on) {
269                         scp->status |= VR_CURSOR_ON;
270                         (*vidsw[scp->sc->adapter]->putc)(scp->sc->adp,
271                             scp->cursor_oldpos,
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;
280                 } else {
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;
286                 }
287         }
288 }
289 #else
290 static void 
291 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
292 {
293         video_adapter_t *adp;
294
295         adp = scp->sc->adp;
296         if (scp->curs_attr.height <= 0) 
297                 /* the text cursor is disabled */
298                 return;
299
300         if (on) {
301                 if (!blink) {
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) {
306                         pxlblinkrate = 0;
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);
311                         else
312                                 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1,
313                                     -1);
314                 }
315         } else {
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;
320         }
321         if (blink)
322                 scp->status |= VR_CURSOR_BLINK;
323         else
324                 scp->status &= ~VR_CURSOR_BLINK;
325 }
326 #endif
327
328 static void
329 gfb_blink(scr_stat *scp, int at, int flip)
330 {
331         if (!(scp->status & VR_CURSOR_BLINK))
332                 return;
333         if (!(++pxlblinkrate & 4))
334                 return;
335         pxlblinkrate = 0;
336         scp->status ^= VR_CURSOR_ON;
337         gfb_cursor(scp, at, scp->status & VR_CURSOR_BLINK,
338             scp->status & VR_CURSOR_ON, flip);
339 }
340
341 #ifndef SC_NO_CUTPASTE
342
343 static void 
344 gfb_mouse(scr_stat *scp, int x, int y, int on)
345 {
346 #ifdef __sparc64__
347                 (*vidsw[scp->sc->adapter]->putm)(scp->sc->adp, x, y,
348                     mouse_pointer, on ? 0xffffffff : 0x0, 22, 12);
349 #else
350         int i, pos;
351
352         if (on) {
353
354                 /* Display the mouse pointer image... */
355                 (*vidsw[scp->sc->adapter]->putm)(scp->sc->adp, x, y,
356                     mouse_pointer, 0xffffffff, 16, 8);
357         } else {
358
359                 /*
360                    Erase the mouse cursor image by redrawing the text
361                    underneath it...
362                 */
363                 return;
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);
369         }
370 #endif
371 }
372
373 #endif /* SC_NO_CUTPASTE */