2 * Copyright (c) 2014 Imre Vadász <imre@vdsz.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
27 #include "opt_syscons.h"
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
32 #include <sys/thread.h>
33 #include <sys/thread2.h>
35 #include <machine/console.h>
37 #include <dev/drm/include/linux/fb.h>
41 #include <bus/isa/isareg.h>
43 static vr_draw_t kms_draw;
44 static vr_draw_cursor_t kms_cursor;
45 static vr_blink_cursor_t kms_blink;
46 static vr_draw_mouse_t kms_mouse;
48 static void kms_nop(scr_stat *scp, ...);
50 static sc_rndr_sw_t kmsrndrsw = {
51 (vr_draw_border_t *)kms_nop,
53 (vr_set_cursor_t *)kms_nop,
56 #ifndef SC_NO_CUTPASTE
59 (vr_draw_mouse_t *)kms_nop;
62 RENDERER(kms, V_INFO_MM_TEXT, kmsrndrsw, kms_set);
64 #ifndef SC_NO_MODE_CHANGE
65 static sc_rndr_sw_t grrndrsw = {
66 (vr_draw_border_t *)kms_nop,
68 (vr_set_cursor_t *)kms_nop,
69 (vr_draw_cursor_t *)kms_nop,
70 (vr_blink_cursor_t *)kms_nop,
71 (vr_draw_mouse_t *)kms_nop,
73 RENDERER(kms, V_INFO_MM_OTHER, grrndrsw, kms_set);
74 #endif /* SC_NO_MODE_CHANGE */
76 RENDERER_MODULE(kms, kms_set);
78 static uint32_t colormap[16] = {
79 0x00000000, /* BLACK */
80 0x000000aa, /* BLUE */
81 0x0000aa00, /* GREEN */
82 0x0000aaaa, /* CYAN */
84 0x00aa00aa, /* MAGENTA */
85 0x00aa5500, /* BROWN */
86 0x00aaaaaa, /* WHITE */
87 0x00555555, /* HIGHLIGHT BLACK */
88 0x005555ff, /* HIGHLIGHT BLUE */
89 0x0055ff55, /* HIGHLIGHT GREEN */
90 0x0055ffff, /* HIGHLIGHT CYAN */
91 0x00ff5555, /* HIGHLIGHT RED */
92 0x00ff55ff, /* HIGHLIGHT MAGENTA */
93 0x00ffff55, /* HIGHLIGHT BROWN */
94 0x00ffffff, /* HIGHLIGHT WHITE */
97 #ifndef SC_NO_CUTPASTE
98 static u_short mouse_and_mask[16] = {
99 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80,
100 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000
102 static u_short mouse_or_mask[16] = {
103 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800,
104 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000
109 kms_nop(scr_stat *scp, ...)
116 kms_draw(scr_stat *scp, int from, int count, int flip)
118 sc_softc_t *sc = scp->sc;
122 vm_offset_t draw_pos, p;
123 int pos, line_width, pixel_size;
125 line_width = sc->fbi->stride;
128 draw_pos = sc->fbi->vaddr +
129 8 * pixel_size * (from % scp->xsize) +
130 scp->font_size * line_width * (from / scp->xsize);
132 if (from + count > scp->xsize * scp->ysize)
133 count = scp->xsize * scp->ysize - from;
135 for (i = from; count-- > 0; i++) {
137 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
140 a = sc_vtb_geta(&scp->vtb, i);
142 fg = colormap[((a & 0xf000) >> 4) >> 8];
143 bg = colormap[(a & 0x0f00) >> 8];
145 fg = colormap[(a & 0x0f00) >> 8];
146 bg = colormap[((a & 0xf000) >> 4) >> 8];
149 for (j = 0; j < scp->font_size; j++, char_data++) {
150 for (pos = 7; pos >= 0; pos--, p += pixel_size)
151 writel(p, *char_data & (1 << pos) ? fg : bg);
152 p += line_width - 8 * pixel_size;
154 draw_pos += 8 * pixel_size;
155 if ((i % scp->xsize) == scp->xsize - 1) {
156 draw_pos += (scp->font_size - 1) * line_width +
157 scp->xpad * pixel_size;
163 draw_kmscursor(scr_stat *scp, int at, int on, int flip)
165 sc_softc_t *sc = scp->sc;
166 int line_width, pixel_size, height;
169 unsigned char *char_data;
170 vm_offset_t draw_pos;
172 line_width = sc->fbi->stride;
175 draw_pos = sc->fbi->vaddr +
176 8 * pixel_size * (at % scp->xsize) +
177 scp->font_size * line_width * (at / scp->xsize) +
178 (scp->font_size - scp->cursor_base - 1) * line_width;
180 a = sc_vtb_geta(&scp->vtb, at);
182 fg = colormap[((on) ? (a & 0x0f00) :
183 ((a & 0xf000) >> 4)) >> 8];
184 bg = colormap[((on) ? ((a & 0xf000) >> 4) :
187 fg = colormap[((on) ? ((a & 0xf000) >> 4) :
189 bg = colormap[((on) ? (a & 0x0f00) :
190 ((a & 0xf000) >> 4)) >> 8];
193 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
194 scp->font_size - scp->cursor_base - 1]);
195 height = imin(scp->cursor_height, scp->font_size);
197 for (i = 0; i < height; i++, char_data--) {
198 for (pos = 7; pos >= 0; pos--, draw_pos += pixel_size)
199 writel(draw_pos, *char_data & (1 << pos) ? fg : bg);
200 draw_pos -= line_width + 8 * pixel_size;
204 static int pxlblinkrate = 0;
207 kms_cursor(scr_stat *scp, int at, int blink, int on, int flip)
209 if (scp->cursor_height <= 0) /* the text cursor is disabled */
214 scp->status |= VR_CURSOR_ON;
215 draw_kmscursor(scp, at, on, flip);
216 } else if (++pxlblinkrate & 4) {
218 scp->status ^= VR_CURSOR_ON;
219 draw_kmscursor(scp, at,
220 scp->status & VR_CURSOR_ON, flip);
223 if (scp->status & VR_CURSOR_ON)
224 draw_kmscursor(scp, at, on, flip);
225 scp->status &= ~VR_CURSOR_ON;
228 scp->status |= VR_CURSOR_BLINK;
230 scp->status &= ~VR_CURSOR_BLINK;
234 kms_blink(scr_stat *scp, int at, int flip)
236 if (!(scp->status & VR_CURSOR_BLINK))
238 if (!(++pxlblinkrate & 4))
241 scp->status ^= VR_CURSOR_ON;
242 draw_kmscursor(scp, at, scp->status & VR_CURSOR_ON, flip);
245 #ifndef SC_NO_CUTPASTE
248 draw_kmsmouse(scr_stat *scp, int x, int y)
250 sc_softc_t *sc = scp->sc;
251 int line_width, pixel_size;
254 vm_offset_t draw_pos;
256 line_width = sc->fbi->stride;
259 xend = imin(x + 8, 8 * (scp->xoff + scp->xsize));
260 yend = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
262 draw_pos = sc->fbi->vaddr + y * line_width + x * pixel_size;
264 for (i = 0; i < (yend - y); i++) {
265 for (j = (xend - x - 1); j >= 0; j--) {
266 if (mouse_or_mask[i] & 1 << (15 - j))
267 writel(draw_pos + pixel_size * j, colormap[15]);
268 else if (mouse_and_mask[i] & 1 << (15 - j))
269 writel(draw_pos + pixel_size * j, colormap[0]);
272 draw_pos += line_width;
277 remove_kmsmouse(scr_stat *scp, int x, int y)
283 /* erase the mouse cursor image */
284 col = x/8 - scp->xoff;
285 row = y/scp->font_size - scp->yoff;
286 pos = row*scp->xsize + col;
287 i = (col < scp->xsize - 1) ? 2 : 1;
288 (*scp->rndr->draw)(scp, pos, i, FALSE);
289 if (row < scp->ysize - 1)
290 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
294 kms_mouse(scr_stat *scp, int x, int y, int on)
297 draw_kmsmouse(scp, x, y);
299 remove_kmsmouse(scp, x, y);
302 #endif /* SC_NO_CUTPASTE */