]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/syscons/scgfbrndr.c
zfs: merge openzfs/zfs@4a1195ca5 (master) into main
[FreeBSD/FreeBSD.git] / sys / dev / syscons / scgfbrndr.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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.
16  *
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.
27  *
28  * Copyright (c) 2000 Andrew Miklic
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include "opt_syscons.h"
35 #ifdef __powerpc__
36 #include "opt_ofwfb.h"
37 #endif
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/fbio.h>
43 #include <sys/consio.h>
44
45 #include <machine/bus.h>
46
47 #include <dev/fb/fbreg.h>
48 #include <dev/syscons/syscons.h>
49
50 #ifndef SC_RENDER_DEBUG
51 #define SC_RENDER_DEBUG         0
52 #endif
53
54 static vr_clear_t               gfb_clear;
55 static vr_draw_border_t         gfb_border;
56 static vr_draw_t                gfb_draw;
57 static vr_set_cursor_t          gfb_cursor_shape;
58 static vr_draw_cursor_t         gfb_cursor;
59 static vr_blink_cursor_t        gfb_blink;
60 #ifndef SC_NO_CUTPASTE
61 static vr_draw_mouse_t          gfb_mouse;
62 #else
63 #define gfb_mouse               (vr_draw_mouse_t *)gfb_nop
64 #endif
65
66 static void                     gfb_nop(scr_stat *scp);
67
68 sc_rndr_sw_t txtrndrsw = {
69         (vr_init_t *)gfb_nop,
70         gfb_clear,
71         gfb_border,
72         gfb_draw,       
73         gfb_cursor_shape,
74         gfb_cursor,
75         gfb_blink,
76         (vr_set_mouse_t *)gfb_nop,
77         gfb_mouse,
78 };
79
80 #ifdef SC_PIXEL_MODE
81 sc_rndr_sw_t gfbrndrsw = {
82         (vr_init_t *)gfb_nop,
83         gfb_clear,
84         gfb_border,
85         gfb_draw,
86         gfb_cursor_shape,
87         gfb_cursor,
88         gfb_blink,
89         (vr_set_mouse_t *)gfb_nop,
90         gfb_mouse,
91 };
92 #endif /* SC_PIXEL_MODE */
93
94 #ifndef SC_NO_MODE_CHANGE
95 sc_rndr_sw_t grrndrsw = {
96         (vr_init_t *)gfb_nop,
97         (vr_clear_t *)gfb_nop,
98         gfb_border,
99         (vr_draw_t *)gfb_nop,
100         (vr_set_cursor_t *)gfb_nop,
101         (vr_draw_cursor_t *)gfb_nop,
102         (vr_blink_cursor_t *)gfb_nop,
103         (vr_set_mouse_t *)gfb_nop,
104         (vr_draw_mouse_t *)gfb_nop,
105 };
106 #endif /* SC_NO_MODE_CHANGE */
107
108 #ifndef SC_NO_CUTPASTE
109 static u_char mouse_pointer[16] = {
110         0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68,
111         0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
112 };
113 #endif
114
115 static void
116 gfb_nop(scr_stat *scp)
117 {
118 }
119
120 /* text mode renderer */
121
122 static void
123 gfb_clear(scr_stat *scp, int c, int attr)
124 {
125         vidd_clear(scp->sc->adp);
126 }
127
128 static void
129 gfb_border(scr_stat *scp, int color)
130 {
131         vidd_set_border(scp->sc->adp, color);
132 }
133
134 static void
135 gfb_draw(scr_stat *scp, int from, int count, int flip)
136 {
137         int c;
138         int a;
139         int i, n;
140         video_adapter_t *adp;
141
142         adp = scp->sc->adp;
143
144         /*
145            Determine if we need to scroll based on the offset
146            and the number of characters to be displayed...
147          */
148         if (from + count > scp->xsize*scp->ysize) {
149                 /*
150                    Calculate the number of characters past the end of the
151                    visible screen...
152                 */
153                 count = (from + count) -
154                     (adp->va_info.vi_width * adp->va_info.vi_height);
155
156                 /*
157                    Calculate the number of rows past the end of the visible
158                    screen...
159                 */
160                 n = (count / adp->va_info.vi_width) + 1;
161
162                 /* Scroll to make room for new text rows... */
163                 vidd_copy(adp, n, 0, n);
164 #if 0
165                 vidd_clear(adp, n);
166 #endif
167
168                 /* Display new text rows... */
169                 vidd_puts(adp, from,
170                     (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), count);
171         }
172
173         /*
174            We don't need to scroll, so we can just put the characters
175            all-at-once...
176         */
177         else {
178                 /*
179                    Determine the method by which we are to display characters
180                    (are we going to print forwards or backwards?
181                    do we need to do a character-by-character copy, then?)...
182                 */
183                 if (flip)
184                         for (i = count; i-- > 0; ++from) {
185                                 c = sc_vtb_getc(&scp->vtb, from);
186                                 a = sc_vtb_geta(&scp->vtb, from) >> 8;
187                                 vidd_putc(adp, from, c,
188                                     (a >> 4) | ((a & 0xf) << 4));
189                         }
190                 else {
191                         vidd_puts(adp, from,
192                             (u_int16_t *)sc_vtb_pointer(&scp->vtb, from),
193                             count);
194                 }
195         }
196 }
197
198 static void 
199 gfb_cursor_shape(scr_stat *scp, int base, int height, int blink)
200 {
201         if (base < 0 || base >= scp->font_size)
202                 return;
203         /* the caller may set height <= 0 in order to disable the cursor */
204 #if 0
205         scp->cursor_base = base;
206         scp->cursor_height = height;
207 #endif
208         vidd_set_hw_cursor_shape(scp->sc->adp, base, height, scp->font_size,
209             blink);
210 }
211
212 static int pxlblinkrate = 0;
213
214 #if defined(SC_OFWFB)
215 static void
216 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
217 {
218         video_adapter_t *adp;
219         int a, c;
220
221         if (scp->curs_attr.height <= 0) /* the text cursor is disabled */
222                 return;
223
224         adp = scp->sc->adp;
225         if(blink) {
226                 scp->status |= VR_CURSOR_BLINK;
227                 if (on) {
228                         scp->status |= VR_CURSOR_ON;
229                         vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
230                 } else {
231                         if (scp->status & VR_CURSOR_ON)
232                                 vidd_set_hw_cursor(adp, -1, -1);
233                         scp->status &= ~VR_CURSOR_ON;
234                 }
235         } else {
236                 scp->status &= ~VR_CURSOR_BLINK;
237                 if(on) {
238                         scp->status |= VR_CURSOR_ON;
239                         vidd_putc(scp->sc->adp, scp->cursor_oldpos,
240                             sc_vtb_getc(&scp->vtb, scp->cursor_oldpos),
241                             sc_vtb_geta(&scp->vtb, scp->cursor_oldpos) >> 8);
242                         a = sc_vtb_geta(&scp->vtb, at) >> 8;
243                         c = sc_vtb_getc(&scp->vtb, at);
244                         vidd_putc(scp->sc->adp, at, c,
245                             (a >> 4) | ((a & 0xf) << 4));
246                 } else {
247                         if (scp->status & VR_CURSOR_ON)
248                                 vidd_putc(scp->sc->adp, at,
249                                     sc_vtb_getc(&scp->vtb, at),
250                                     sc_vtb_geta(&scp->vtb, at) >> 8);
251                         scp->status &= ~VR_CURSOR_ON;
252                 }
253         }
254 }
255 #else
256 static void 
257 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
258 {
259         video_adapter_t *adp;
260
261         adp = scp->sc->adp;
262         if (scp->curs_attr.height <= 0) 
263                 /* the text cursor is disabled */
264                 return;
265
266         if (on) {
267                 if (!blink) {
268                         scp->status |= VR_CURSOR_ON;
269                         vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
270                 } else if (++pxlblinkrate & 4) {
271                         pxlblinkrate = 0;
272                         scp->status ^= VR_CURSOR_ON;
273                         if(scp->status & VR_CURSOR_ON)
274                                 vidd_set_hw_cursor(adp, at%scp->xsize,
275                                     at/scp->xsize);
276                         else
277                                 vidd_set_hw_cursor(adp, -1, -1);
278                 }
279         } else {
280                 if (scp->status & VR_CURSOR_ON)
281                         vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
282                 scp->status &= ~VR_CURSOR_ON;
283         }
284         if (blink)
285                 scp->status |= VR_CURSOR_BLINK;
286         else
287                 scp->status &= ~VR_CURSOR_BLINK;
288 }
289 #endif
290
291 static void
292 gfb_blink(scr_stat *scp, int at, int flip)
293 {
294         if (!(scp->status & VR_CURSOR_BLINK))
295                 return;
296         if (!(++pxlblinkrate & 4))
297                 return;
298         pxlblinkrate = 0;
299         scp->status ^= VR_CURSOR_ON;
300         gfb_cursor(scp, at, scp->status & VR_CURSOR_BLINK,
301             scp->status & VR_CURSOR_ON, flip);
302 }
303
304 #ifndef SC_NO_CUTPASTE
305
306 static void 
307 gfb_mouse(scr_stat *scp, int x, int y, int on)
308 {
309         if (on) {
310                 vidd_putm(scp->sc->adp, x, y, mouse_pointer,
311                     0xffffffff, 16, 8);
312         } else {
313                 /* XXX: removal is incomplete for h/w cursors and borders. */
314         }
315 }
316
317 #endif /* SC_NO_CUTPASTE */