Commit | Line | Data |
---|---|---|
984263bc MD |
1 | /*- |
2 | * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> | |
3 | * All rights reserved. | |
4 | * | |
2a85d763 MD |
5 | * This code is derived from software contributed to The DragonFly Project |
6 | * by Sascha Wildner <saw@online.de> | |
7 | * | |
984263bc MD |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer as | |
13 | * the first lines of this file unmodified. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | |
15 | * notice, this list of conditions and the following disclaimer in the | |
16 | * documentation and/or other materials provided with the distribution. | |
17 | * | |
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR | |
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
21 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
28 | * | |
29 | * $FreeBSD: src/sys/dev/syscons/scvgarndr.c,v 1.5.2.3 2001/07/28 12:51:47 yokota Exp $ | |
30 | */ | |
31 | ||
32 | #include "opt_syscons.h" | |
33 | #include "opt_vga.h" | |
34 | ||
35 | #include <sys/param.h> | |
36 | #include <sys/systm.h> | |
37 | #include <sys/kernel.h> | |
22ff886e | 38 | #include <sys/thread.h> |
984263bc MD |
39 | |
40 | #include <machine/console.h> | |
41 | ||
1f2de5d4 MD |
42 | #include <dev/video/fb/fbreg.h> |
43 | #include <dev/video/fb/vgareg.h> | |
44 | #include "syscons.h" | |
984263bc | 45 | |
1f2de5d4 | 46 | #include <bus/isa/isareg.h> |
984263bc | 47 | |
984263bc MD |
48 | static vr_draw_border_t vga_txtborder; |
49 | static vr_draw_t vga_txtdraw; | |
50 | static vr_set_cursor_t vga_txtcursor_shape; | |
51 | static vr_draw_cursor_t vga_txtcursor; | |
52 | static vr_blink_cursor_t vga_txtblink; | |
53 | #ifndef SC_NO_CUTPASTE | |
54 | static vr_draw_mouse_t vga_txtmouse; | |
55 | #else | |
2a85d763 | 56 | #define vga_txtmouse (vr_draw_mouse_t *)vga_nop |
984263bc MD |
57 | #endif |
58 | ||
59 | #ifdef SC_PIXEL_MODE | |
2a85d763 | 60 | static vr_draw_border_t vga_pxlborder_direct; |
771006e1 | 61 | static vr_draw_border_t vga_pxlborder_packed; |
2a85d763 | 62 | static vr_draw_border_t vga_pxlborder_planar; |
2a85d763 | 63 | static vr_draw_t vga_vgadraw_direct; |
771006e1 | 64 | static vr_draw_t vga_vgadraw_packed; |
2a85d763 | 65 | static vr_draw_t vga_vgadraw_planar; |
984263bc | 66 | static vr_set_cursor_t vga_pxlcursor_shape; |
2a85d763 | 67 | static vr_draw_cursor_t vga_pxlcursor_direct; |
771006e1 | 68 | static vr_draw_cursor_t vga_pxlcursor_packed; |
2a85d763 MD |
69 | static vr_draw_cursor_t vga_pxlcursor_planar; |
70 | static vr_blink_cursor_t vga_pxlblink_direct; | |
771006e1 | 71 | static vr_blink_cursor_t vga_pxlblink_packed; |
2a85d763 | 72 | static vr_blink_cursor_t vga_pxlblink_planar; |
984263bc | 73 | #ifndef SC_NO_CUTPASTE |
2a85d763 | 74 | static vr_draw_mouse_t vga_pxlmouse_direct; |
771006e1 | 75 | static vr_draw_mouse_t vga_pxlmouse_packed; |
2a85d763 | 76 | static vr_draw_mouse_t vga_pxlmouse_planar; |
984263bc | 77 | #else |
4097d120 | 78 | #define vga_pxlmouse_direct (vr_draw_mouse_t *)vga_nop |
771006e1 | 79 | #define vga_pxlmouse_packed (vr_draw_mouse_t *)vga_nop |
4097d120 | 80 | #define vga_pxlmouse_planar (vr_draw_mouse_t *)vga_nop |
984263bc MD |
81 | #endif |
82 | #endif /* SC_PIXEL_MODE */ | |
83 | ||
84 | #ifndef SC_NO_MODE_CHANGE | |
85 | static vr_draw_border_t vga_grborder; | |
86 | #endif | |
87 | ||
88 | static void vga_nop(scr_stat *scp, ...); | |
89 | ||
984263bc | 90 | static sc_rndr_sw_t txtrndrsw = { |
984263bc MD |
91 | vga_txtborder, |
92 | vga_txtdraw, | |
93 | vga_txtcursor_shape, | |
94 | vga_txtcursor, | |
95 | vga_txtblink, | |
984263bc MD |
96 | vga_txtmouse, |
97 | }; | |
21343892 | 98 | RENDERER(vga, V_INFO_MM_TEXT, txtrndrsw, vga_set); |
984263bc MD |
99 | |
100 | #ifdef SC_PIXEL_MODE | |
21343892 SW |
101 | static sc_rndr_sw_t directrndrsw = { |
102 | vga_pxlborder_direct, | |
103 | vga_vgadraw_direct, | |
104 | vga_pxlcursor_shape, | |
105 | vga_pxlcursor_direct, | |
106 | vga_pxlblink_direct, | |
107 | vga_pxlmouse_direct, | |
984263bc | 108 | }; |
21343892 | 109 | RENDERER(vga, V_INFO_MM_DIRECT, directrndrsw, vga_set); |
771006e1 SW |
110 | |
111 | static sc_rndr_sw_t packedrndrsw = { | |
112 | vga_pxlborder_packed, | |
113 | vga_vgadraw_packed, | |
114 | vga_pxlcursor_shape, | |
115 | vga_pxlcursor_packed, | |
116 | vga_pxlblink_packed, | |
117 | vga_pxlmouse_packed, | |
118 | }; | |
119 | RENDERER(vga, V_INFO_MM_PACKED, packedrndrsw, vga_set); | |
120 | ||
121 | static sc_rndr_sw_t planarrndrsw = { | |
122 | vga_pxlborder_planar, | |
123 | vga_vgadraw_planar, | |
124 | vga_pxlcursor_shape, | |
125 | vga_pxlcursor_planar, | |
126 | vga_pxlblink_planar, | |
127 | vga_pxlmouse_planar, | |
128 | }; | |
129 | RENDERER(vga, V_INFO_MM_PLANAR, planarrndrsw, vga_set); | |
984263bc MD |
130 | #endif /* SC_PIXEL_MODE */ |
131 | ||
132 | #ifndef SC_NO_MODE_CHANGE | |
133 | static sc_rndr_sw_t grrndrsw = { | |
984263bc MD |
134 | vga_grborder, |
135 | (vr_draw_t *)vga_nop, | |
136 | (vr_set_cursor_t *)vga_nop, | |
137 | (vr_draw_cursor_t *)vga_nop, | |
138 | (vr_blink_cursor_t *)vga_nop, | |
984263bc MD |
139 | (vr_draw_mouse_t *)vga_nop, |
140 | }; | |
21343892 | 141 | RENDERER(vga, V_INFO_MM_OTHER, grrndrsw, vga_set); |
984263bc MD |
142 | #endif /* SC_NO_MODE_CHANGE */ |
143 | ||
144 | RENDERER_MODULE(vga, vga_set); | |
145 | ||
146 | #ifndef SC_NO_CUTPASTE | |
147 | static u_short mouse_and_mask[16] = { | |
148 | 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, | |
149 | 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000 | |
150 | }; | |
151 | static u_short mouse_or_mask[16] = { | |
152 | 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800, | |
153 | 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000 | |
154 | }; | |
155 | #endif | |
156 | ||
157 | static void | |
158 | vga_nop(scr_stat *scp, ...) | |
159 | { | |
160 | } | |
161 | ||
162 | /* text mode renderer */ | |
163 | ||
984263bc MD |
164 | static void |
165 | vga_txtborder(scr_stat *scp, int color) | |
166 | { | |
167 | (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color); | |
168 | } | |
169 | ||
170 | static void | |
7ae6dbf0 | 171 | vga_txtdraw(scr_stat *scp, int from, int count, int flip) |
984263bc | 172 | { |
47d95543 | 173 | uint16_t *p; |
984263bc MD |
174 | int c; |
175 | int a; | |
176 | ||
177 | if (from + count > scp->xsize*scp->ysize) | |
178 | count = scp->xsize*scp->ysize - from; | |
179 | ||
180 | if (flip) { | |
47d95543 | 181 | for (p = scp->scr.vtb_buffer + from; count-- > 0; ++from) { |
984263bc MD |
182 | c = sc_vtb_getc(&scp->vtb, from); |
183 | a = sc_vtb_geta(&scp->vtb, from); | |
184 | a = (a & 0x8800) | ((a & 0x7000) >> 4) | |
185 | | ((a & 0x0700) << 4); | |
186 | p = sc_vtb_putchar(&scp->scr, p, c, a); | |
187 | } | |
188 | } else { | |
189 | sc_vtb_copy(&scp->vtb, from, &scp->scr, from, count); | |
190 | } | |
191 | } | |
192 | ||
193 | static void | |
194 | vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink) | |
195 | { | |
219917ca | 196 | if (base < 0 || base >= scp->font_height) |
984263bc | 197 | return; |
5688255a | 198 | |
984263bc MD |
199 | /* the caller may set height <= 0 in order to disable the cursor */ |
200 | #if 0 | |
201 | scp->cursor_base = base; | |
202 | scp->cursor_height = height; | |
203 | #endif | |
204 | (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp, | |
205 | base, height, | |
219917ca SW |
206 | scp->font_height, |
207 | blink); | |
5688255a | 208 | |
984263bc MD |
209 | } |
210 | ||
211 | static void | |
212 | draw_txtcharcursor(scr_stat *scp, int at, u_short c, u_short a, int flip) | |
213 | { | |
214 | sc_softc_t *sc; | |
215 | ||
216 | sc = scp->sc; | |
217 | scp->cursor_saveunder_char = c; | |
218 | scp->cursor_saveunder_attr = a; | |
219 | ||
220 | #ifndef SC_NO_FONT_LOADING | |
221 | if (sc->flags & SC_CHAR_CURSOR) { | |
222 | unsigned char *font; | |
223 | int h; | |
224 | int i; | |
225 | ||
219917ca | 226 | if (scp->font_height < 14) { |
984263bc MD |
227 | font = sc->font_8; |
228 | h = 8; | |
219917ca | 229 | } else if (scp->font_height >= 16) { |
984263bc MD |
230 | font = sc->font_16; |
231 | h = 16; | |
232 | } else { | |
233 | font = sc->font_14; | |
234 | h = 14; | |
235 | } | |
766a68c8 | 236 | if (scp->cursor_base >= h) |
984263bc MD |
237 | return; |
238 | if (flip) | |
239 | a = (a & 0x8800) | |
240 | | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4); | |
241 | bcopy(font + c*h, font + sc->cursor_char*h, h); | |
242 | font = font + sc->cursor_char*h; | |
243 | for (i = imax(h - scp->cursor_base - scp->cursor_height, 0); | |
244 | i < h - scp->cursor_base; ++i) { | |
245 | font[i] ^= 0xff; | |
246 | } | |
247 | sc->font_loading_in_progress = TRUE; | |
248 | /* XXX */ | |
249 | (*vidsw[sc->adapter]->load_font)(sc->adp, 0, h, font, | |
250 | sc->cursor_char, 1); | |
251 | sc->font_loading_in_progress = FALSE; | |
252 | sc_vtb_putc(&scp->scr, at, sc->cursor_char, a); | |
253 | } else | |
254 | #endif /* SC_NO_FONT_LOADING */ | |
255 | { | |
256 | if ((a & 0x7000) == 0x7000) { | |
257 | a &= 0x8f00; | |
258 | if ((a & 0x0700) == 0) | |
259 | a |= 0x0700; | |
260 | } else { | |
261 | a |= 0x7000; | |
262 | if ((a & 0x0700) == 0x0700) | |
263 | a &= 0xf000; | |
264 | } | |
265 | if (flip) | |
266 | a = (a & 0x8800) | |
267 | | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4); | |
268 | sc_vtb_putc(&scp->scr, at, c, a); | |
269 | } | |
270 | } | |
271 | ||
272 | static void | |
273 | vga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip) | |
274 | { | |
275 | video_adapter_t *adp; | |
276 | int cursor_attr; | |
277 | ||
278 | if (scp->cursor_height <= 0) /* the text cursor is disabled */ | |
279 | return; | |
280 | ||
281 | adp = scp->sc->adp; | |
282 | if (blink) { | |
283 | scp->status |= VR_CURSOR_BLINK; | |
284 | if (on) { | |
285 | scp->status |= VR_CURSOR_ON; | |
286 | (*vidsw[adp->va_index]->set_hw_cursor)(adp, | |
287 | at%scp->xsize, | |
288 | at/scp->xsize); | |
289 | } else { | |
290 | if (scp->status & VR_CURSOR_ON) | |
291 | (*vidsw[adp->va_index]->set_hw_cursor)(adp, | |
292 | -1, -1); | |
293 | scp->status &= ~VR_CURSOR_ON; | |
294 | } | |
295 | } else { | |
296 | scp->status &= ~VR_CURSOR_BLINK; | |
297 | if (on) { | |
298 | scp->status |= VR_CURSOR_ON; | |
299 | draw_txtcharcursor(scp, at, | |
300 | sc_vtb_getc(&scp->scr, at), | |
301 | sc_vtb_geta(&scp->scr, at), | |
302 | flip); | |
303 | } else { | |
304 | cursor_attr = scp->cursor_saveunder_attr; | |
305 | if (flip) | |
306 | cursor_attr = (cursor_attr & 0x8800) | |
307 | | ((cursor_attr & 0x7000) >> 4) | |
308 | | ((cursor_attr & 0x0700) << 4); | |
309 | if (scp->status & VR_CURSOR_ON) | |
310 | sc_vtb_putc(&scp->scr, at, | |
311 | scp->cursor_saveunder_char, | |
312 | cursor_attr); | |
313 | scp->status &= ~VR_CURSOR_ON; | |
314 | } | |
315 | } | |
316 | } | |
317 | ||
318 | static void | |
319 | vga_txtblink(scr_stat *scp, int at, int flip) | |
320 | { | |
321 | } | |
322 | ||
ef56dbd7 FT |
323 | int sc_txtmouse_no_retrace_wait; |
324 | ||
984263bc MD |
325 | #ifndef SC_NO_CUTPASTE |
326 | ||
327 | static void | |
328 | draw_txtmouse(scr_stat *scp, int x, int y) | |
329 | { | |
330 | #ifndef SC_ALT_MOUSE_IMAGE | |
331 | if (ISMOUSEAVAIL(scp->sc->adp->va_flags)) { | |
332 | u_char font_buf[128]; | |
333 | u_short cursor[32]; | |
334 | u_char c; | |
335 | int pos; | |
336 | int xoffset, yoffset; | |
984263bc MD |
337 | int i; |
338 | ||
339 | /* prepare mousepointer char's bitmaps */ | |
219917ca SW |
340 | pos = (y / scp->font_height - scp->yoff) * scp->xsize + |
341 | x / scp->font_width - scp->xoff; | |
342 | bcopy(scp->font + sc_vtb_getc(&scp->scr, pos) * scp->font_height, | |
343 | &font_buf[0], scp->font_height); | |
344 | bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1) * scp->font_height, | |
345 | &font_buf[32], scp->font_height); | |
984263bc | 346 | bcopy(scp->font |
219917ca SW |
347 | + sc_vtb_getc(&scp->scr, pos + scp->xsize) * scp->font_height, |
348 | &font_buf[64], scp->font_height); | |
349 | bcopy(scp->font + | |
350 | sc_vtb_getc(&scp->scr, pos + scp->xsize + 1) * scp->font_height, | |
351 | &font_buf[96], scp->font_height); | |
352 | for (i = 0; i < scp->font_height; ++i) { | |
353 | cursor[i] = (font_buf[i]<<8) | font_buf[i+32]; | |
354 | cursor[i + scp->font_height] = (font_buf[i+64]<<8) | | |
355 | font_buf[i+96]; | |
984263bc MD |
356 | } |
357 | ||
358 | /* now and-or in the mousepointer image */ | |
219917ca SW |
359 | xoffset = x % scp->font_width; |
360 | yoffset = y % scp->font_height; | |
984263bc MD |
361 | for (i = 0; i < 16; ++i) { |
362 | cursor[i + yoffset] = | |
363 | (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset)) | |
364 | | (mouse_or_mask[i] >> xoffset); | |
365 | } | |
219917ca | 366 | for (i = 0; i < scp->font_height; ++i) { |
984263bc MD |
367 | font_buf[i] = (cursor[i] & 0xff00) >> 8; |
368 | font_buf[i + 32] = cursor[i] & 0xff; | |
219917ca SW |
369 | font_buf[i + 64] = (cursor[i + scp->font_height] & 0xff00) >> 8; |
370 | font_buf[i + 96] = cursor[i + scp->font_height] & 0xff; | |
984263bc MD |
371 | } |
372 | ||
373 | #if 1 | |
374 | /* wait for vertical retrace to avoid jitter on some videocards */ | |
ef56dbd7 FT |
375 | while (!sc_txtmouse_no_retrace_wait && |
376 | !(inb(CRTC + 6) & 0x08)) | |
377 | /* idle */ ; | |
984263bc MD |
378 | #endif |
379 | c = scp->sc->mouse_char; | |
380 | (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf, | |
381 | c, 4); | |
382 | ||
383 | sc_vtb_putc(&scp->scr, pos, c, sc_vtb_geta(&scp->scr, pos)); | |
384 | /* FIXME: may be out of range! */ | |
385 | sc_vtb_putc(&scp->scr, pos + scp->xsize, c + 2, | |
386 | sc_vtb_geta(&scp->scr, pos + scp->xsize)); | |
387 | if (x < (scp->xsize - 1)*8) { | |
388 | sc_vtb_putc(&scp->scr, pos + 1, c + 1, | |
389 | sc_vtb_geta(&scp->scr, pos + 1)); | |
390 | sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, c + 3, | |
391 | sc_vtb_geta(&scp->scr, pos + scp->xsize + 1)); | |
392 | } | |
393 | } else | |
394 | #endif /* SC_ALT_MOUSE_IMAGE */ | |
395 | { | |
396 | /* Red, magenta and brown are mapped to green to to keep it readable */ | |
397 | static const int col_conv[16] = { | |
398 | 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14 | |
399 | }; | |
400 | int pos; | |
401 | int color; | |
402 | int a; | |
403 | ||
219917ca SW |
404 | pos = (y / scp->font_height - scp->yoff)* |
405 | scp->xsize + x / scp->font_width - scp->xoff; | |
984263bc MD |
406 | a = sc_vtb_geta(&scp->scr, pos); |
407 | if (scp->sc->adp->va_flags & V_ADP_COLOR) | |
408 | color = (col_conv[(a & 0xf000) >> 12] << 12) | |
409 | | ((a & 0x0f00) | 0x0800); | |
410 | else | |
411 | color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4); | |
412 | sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color); | |
413 | } | |
22ff886e | 414 | |
984263bc MD |
415 | } |
416 | ||
417 | static void | |
418 | remove_txtmouse(scr_stat *scp, int x, int y) | |
419 | { | |
420 | } | |
421 | ||
422 | static void | |
423 | vga_txtmouse(scr_stat *scp, int x, int y, int on) | |
424 | { | |
425 | if (on) | |
426 | draw_txtmouse(scp, x, y); | |
427 | else | |
428 | remove_txtmouse(scp, x, y); | |
429 | } | |
430 | ||
431 | #endif /* SC_NO_CUTPASTE */ | |
432 | ||
433 | #ifdef SC_PIXEL_MODE | |
434 | ||
435 | /* pixel (raster text) mode renderer */ | |
436 | ||
984263bc | 437 | static void |
2a85d763 MD |
438 | vga_pxlborder_direct(scr_stat *scp, int color) |
439 | { | |
a5eb78ad SW |
440 | int i, x, y; |
441 | int line_width, pixel_size; | |
442 | uint32_t u32 = 0; | |
443 | vm_offset_t draw_pos, draw_end, p; | |
2a85d763 MD |
444 | |
445 | line_width = scp->sc->adp->va_line_width; | |
446 | pixel_size = scp->sc->adp->va_info.vi_pixel_size; | |
447 | ||
a5eb78ad SW |
448 | for (i = 0; i < 4 / pixel_size; ++i) |
449 | u32 += scp->ega_palette[color] << (i * 8 * pixel_size); | |
450 | ||
2a85d763 | 451 | if (scp->yoff > 0) { |
a5eb78ad | 452 | draw_pos = scp->sc->adp->va_window; |
219917ca | 453 | draw_end = draw_pos + line_width * scp->yoff * scp->font_height; |
2a85d763 | 454 | |
a5eb78ad SW |
455 | for (p = draw_pos; p < draw_end; p += 4) |
456 | writel(p, u32); | |
2a85d763 MD |
457 | } |
458 | ||
219917ca | 459 | y = (scp->yoff + scp->ysize) * scp->font_height; |
2a85d763 MD |
460 | |
461 | if (scp->ypixel > y) { | |
a5eb78ad SW |
462 | draw_pos = scp->sc->adp->va_window + line_width * y; |
463 | draw_end = draw_pos + line_width * (scp->ypixel - y); | |
2a85d763 | 464 | |
a5eb78ad SW |
465 | for (p = draw_pos; p < draw_end; p += 4) |
466 | writel(p, u32); | |
2a85d763 MD |
467 | } |
468 | ||
219917ca SW |
469 | y = scp->yoff * scp->font_height; |
470 | x = scp->xpixel / scp->font_width - scp->xoff - scp->xsize; | |
2a85d763 | 471 | |
219917ca | 472 | for (i = 0; i < scp->ysize * scp->font_height; ++i) { |
2a85d763 | 473 | if (scp->xoff > 0) { |
a5eb78ad SW |
474 | draw_pos = scp->sc->adp->va_window + |
475 | line_width * (y + i); | |
219917ca SW |
476 | draw_end = draw_pos + |
477 | scp->xoff * scp->font_width * pixel_size; | |
2a85d763 | 478 | |
a5eb78ad SW |
479 | for (p = draw_pos; p < draw_end; p += 4) |
480 | writel(p, u32); | |
2a85d763 MD |
481 | } |
482 | ||
483 | if (x > 0) { | |
a5eb78ad SW |
484 | draw_pos = scp->sc->adp->va_window + |
485 | line_width * (y + i) + | |
2a85d763 MD |
486 | scp->xoff * 8 * pixel_size + |
487 | scp->xsize * 8 * pixel_size; | |
a5eb78ad | 488 | draw_end = draw_pos + x * 8 * pixel_size; |
2a85d763 | 489 | |
a5eb78ad SW |
490 | for (p = draw_pos; p < draw_end; p += 4) |
491 | writel(p, u32); | |
2a85d763 MD |
492 | } |
493 | } | |
494 | } | |
495 | ||
771006e1 SW |
496 | static void |
497 | vga_pxlborder_packed(scr_stat *scp, int color) | |
498 | { | |
499 | int i, x, y; | |
500 | int line_width; | |
501 | uint32_t u32; | |
502 | vm_offset_t draw_pos, draw_end, p; | |
503 | ||
504 | line_width = scp->sc->adp->va_line_width; | |
505 | u32 = (color << 24) + (color << 16) + (color << 8) + color; | |
506 | ||
507 | if (scp->yoff > 0) { | |
508 | draw_pos = scp->sc->adp->va_window; | |
219917ca | 509 | draw_end = draw_pos + line_width * scp->yoff * scp->font_height; |
771006e1 SW |
510 | |
511 | for (p = draw_pos; p < draw_end; p += 4) | |
512 | writel(p, u32); | |
513 | } | |
514 | ||
219917ca | 515 | y = (scp->yoff + scp->ysize) * scp->font_height; |
771006e1 SW |
516 | |
517 | if (scp->ypixel > y) { | |
518 | draw_pos = scp->sc->adp->va_window + line_width * y; | |
519 | draw_end = draw_pos + line_width * (scp->ypixel - y); | |
520 | ||
521 | for (p = draw_pos; p < draw_end; p += 4) | |
522 | writel(p, u32); | |
523 | } | |
524 | ||
219917ca SW |
525 | y = scp->yoff * scp->font_height; |
526 | x = scp->xpixel / scp->font_width - scp->xoff - scp->xsize; | |
771006e1 | 527 | |
219917ca | 528 | for (i = 0; i < scp->ysize * scp->font_height; ++i) { |
771006e1 SW |
529 | if (scp->xoff > 0) { |
530 | draw_pos = scp->sc->adp->va_window + | |
531 | line_width * (y + i); | |
219917ca | 532 | draw_end = draw_pos + scp->xoff * scp->font_width; |
771006e1 SW |
533 | |
534 | for (p = draw_pos; p < draw_end; p += 4) | |
535 | writel(p, u32); | |
536 | } | |
537 | ||
538 | if (x > 0) { | |
539 | draw_pos = scp->sc->adp->va_window + | |
540 | line_width * (y + i) + scp->xoff * 8 + | |
541 | scp->xsize * 8; | |
542 | draw_end = draw_pos + x * 8; | |
543 | ||
544 | for (p = draw_pos; p < draw_end; p += 4) | |
545 | writel(p, u32); | |
546 | } | |
547 | } | |
548 | } | |
549 | ||
2a85d763 MD |
550 | static void |
551 | vga_pxlborder_planar(scr_stat *scp, int color) | |
984263bc MD |
552 | { |
553 | vm_offset_t p; | |
554 | int line_width; | |
555 | int x; | |
556 | int y; | |
557 | int i; | |
558 | ||
2efb75f3 | 559 | lwkt_gettoken(&vga_token); |
22ff886e | 560 | |
984263bc MD |
561 | (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color); |
562 | ||
563 | outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ | |
564 | outw(GDCIDX, 0x0003); /* data rotate/function select */ | |
565 | outw(GDCIDX, 0x0f01); /* set/reset enable */ | |
566 | outw(GDCIDX, 0xff08); /* bit mask */ | |
567 | outw(GDCIDX, (color << 8) | 0x00); /* set/reset */ | |
568 | line_width = scp->sc->adp->va_line_width; | |
569 | p = scp->sc->adp->va_window; | |
570 | if (scp->yoff > 0) | |
219917ca SW |
571 | bzero_io((void *)p, line_width*scp->yoff*scp->font_height); |
572 | y = (scp->yoff + scp->ysize)*scp->font_height; | |
984263bc | 573 | if (scp->ypixel > y) |
219917ca SW |
574 | bzero_io((void *)(p + line_width*y), |
575 | line_width*(scp->ypixel - y)); | |
576 | y = scp->yoff*scp->font_height; | |
577 | x = scp->xpixel/scp->font_width - scp->xoff - scp->xsize; | |
578 | for (i = 0; i < scp->ysize*scp->font_height; ++i) { | |
984263bc MD |
579 | if (scp->xoff > 0) |
580 | bzero_io((void *)(p + line_width*(y + i)), scp->xoff); | |
581 | if (x > 0) | |
582 | bzero_io((void *)(p + line_width*(y + i) | |
583 | + scp->xoff + scp->xsize), x); | |
584 | } | |
585 | outw(GDCIDX, 0x0000); /* set/reset */ | |
586 | outw(GDCIDX, 0x0001); /* set/reset enable */ | |
2efb75f3 | 587 | lwkt_reltoken(&vga_token); |
984263bc MD |
588 | } |
589 | ||
2a85d763 | 590 | static void |
7ae6dbf0 | 591 | vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip) |
2a85d763 | 592 | { |
2a85d763 | 593 | int line_width, pixel_size; |
a5eb78ad SW |
594 | int a, i, j, k, l, pos; |
595 | uint32_t fg, bg, u32; | |
596 | unsigned char *char_data; | |
597 | vm_offset_t draw_pos, p; | |
2a85d763 MD |
598 | |
599 | line_width = scp->sc->adp->va_line_width; | |
600 | pixel_size = scp->sc->adp->va_info.vi_pixel_size; | |
601 | ||
a5eb78ad | 602 | draw_pos = VIDEO_MEMORY_POS(scp, from, 8 * pixel_size); |
2a85d763 MD |
603 | |
604 | if (from + count > scp->xsize * scp->ysize) | |
605 | count = scp->xsize * scp->ysize - from; | |
606 | ||
607 | for (i = from; count-- > 0; ++i) { | |
608 | a = sc_vtb_geta(&scp->vtb, i); | |
609 | ||
610 | if (flip) { | |
a5eb78ad SW |
611 | fg = scp->ega_palette[(((a & 0x7000) >> 4) | |
612 | (a & 0x0800)) >> 8]; | |
613 | bg = scp->ega_palette[(((a & 0x8000) >> 4) | | |
614 | (a & 0x0700)) >> 8]; | |
2a85d763 | 615 | } else { |
a5eb78ad SW |
616 | fg = scp->ega_palette[(a & 0x0f00) >> 8]; |
617 | bg = scp->ega_palette[(a & 0xf000) >> 12]; | |
2a85d763 MD |
618 | } |
619 | ||
a5eb78ad SW |
620 | p = draw_pos; |
621 | char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) * | |
219917ca | 622 | scp->font_height]); |
2a85d763 | 623 | |
219917ca | 624 | for (j = 0; j < scp->font_height; ++j, ++char_data) { |
a5eb78ad SW |
625 | pos = 7; |
626 | ||
627 | for (k = 0; k < 2 * pixel_size; ++k) { | |
628 | u32 = 0; | |
629 | ||
630 | for (l = 0; l < 4 / pixel_size; ++l) { | |
631 | u32 += (*char_data & (1 << pos--) ? | |
632 | fg : bg) << (l * 8 * pixel_size); | |
633 | } | |
634 | ||
635 | writel(p, u32); | |
636 | p += 4; | |
2a85d763 MD |
637 | } |
638 | ||
a5eb78ad | 639 | p += line_width - 8 * pixel_size; |
2a85d763 MD |
640 | } |
641 | ||
a5eb78ad | 642 | draw_pos += 8 * pixel_size; |
2a85d763 MD |
643 | |
644 | if ((i % scp->xsize) == scp->xsize - 1) | |
a5eb78ad | 645 | draw_pos += scp->xoff * 16 * pixel_size + |
219917ca | 646 | (scp->font_height - 1) * line_width; |
2a85d763 MD |
647 | } |
648 | } | |
649 | ||
771006e1 | 650 | static void |
7ae6dbf0 | 651 | vga_vgadraw_packed(scr_stat *scp, int from, int count, int flip) |
771006e1 SW |
652 | { |
653 | int line_width; | |
654 | int a, i, j; | |
655 | uint32_t fg, bg, u32; | |
656 | unsigned char *char_data; | |
657 | vm_offset_t draw_pos, p; | |
658 | ||
659 | line_width = scp->sc->adp->va_line_width; | |
660 | ||
661 | draw_pos = VIDEO_MEMORY_POS(scp, from, 8); | |
662 | ||
663 | if (from + count > scp->xsize * scp->ysize) | |
664 | count = scp->xsize * scp->ysize - from; | |
665 | ||
666 | for (i = from; count-- > 0; ++i) { | |
667 | a = sc_vtb_geta(&scp->vtb, i); | |
668 | ||
669 | if (flip) { | |
670 | fg = ((a & 0xf000) >> 4) >> 8; | |
671 | bg = (a & 0x0f00) >> 8; | |
672 | } else { | |
673 | fg = (a & 0x0f00) >> 8; | |
674 | bg = ((a & 0xf000) >> 4) >> 8; | |
675 | } | |
676 | ||
677 | p = draw_pos; | |
678 | char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) * | |
219917ca | 679 | scp->font_height]); |
771006e1 | 680 | |
219917ca | 681 | for (j = 0; j < scp->font_height; ++j, ++char_data) { |
771006e1 SW |
682 | u32 = ((*char_data & 1 ? fg : bg) << 24) + |
683 | ((*char_data & 2 ? fg : bg) << 16) + | |
684 | ((*char_data & 4 ? fg : bg) << 8) + | |
685 | (*char_data & 8 ? fg : bg); | |
686 | writel(p + 4, u32); | |
687 | ||
688 | u32 = ((*char_data & 16 ? fg : bg) << 24) + | |
689 | ((*char_data & 32 ? fg : bg) << 16) + | |
690 | ((*char_data & 64 ? fg : bg) << 8) + | |
691 | (*char_data & 128 ? fg : bg); | |
692 | writel(p, u32); | |
693 | ||
694 | p += line_width; | |
695 | } | |
696 | ||
219917ca | 697 | draw_pos += scp->font_width; |
771006e1 SW |
698 | |
699 | if ((i % scp->xsize) == scp->xsize - 1) | |
700 | draw_pos += scp->xoff * 16 + | |
219917ca | 701 | (scp->font_height - 1) * line_width; |
771006e1 SW |
702 | } |
703 | } | |
704 | ||
2a85d763 | 705 | static void |
7ae6dbf0 | 706 | vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip) |
984263bc MD |
707 | { |
708 | vm_offset_t d; | |
709 | vm_offset_t e; | |
710 | u_char *f; | |
711 | u_short bg; | |
712 | u_short col1, col2; | |
713 | int line_width; | |
714 | int i, j; | |
715 | int a; | |
716 | u_char c; | |
717 | ||
2a85d763 MD |
718 | d = VIDEO_MEMORY_POS(scp, from, 1); |
719 | ||
984263bc | 720 | line_width = scp->sc->adp->va_line_width; |
984263bc MD |
721 | |
722 | outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ | |
723 | outw(GDCIDX, 0x0003); /* data rotate/function select */ | |
724 | outw(GDCIDX, 0x0f01); /* set/reset enable */ | |
725 | outw(GDCIDX, 0xff08); /* bit mask */ | |
726 | bg = -1; | |
727 | if (from + count > scp->xsize*scp->ysize) | |
728 | count = scp->xsize*scp->ysize - from; | |
729 | for (i = from; count-- > 0; ++i) { | |
730 | a = sc_vtb_geta(&scp->vtb, i); | |
731 | if (flip) { | |
732 | col1 = ((a & 0x7000) >> 4) | (a & 0x0800); | |
733 | col2 = ((a & 0x8000) >> 4) | (a & 0x0700); | |
734 | } else { | |
735 | col1 = (a & 0x0f00); | |
736 | col2 = (a & 0xf000) >> 4; | |
737 | } | |
738 | /* set background color in EGA/VGA latch */ | |
739 | if (bg != col2) { | |
740 | bg = col2; | |
741 | outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ | |
742 | outw(GDCIDX, bg | 0x00); /* set/reset */ | |
743 | writeb(d, 0); | |
744 | c = readb(d); /* set bg color in the latch */ | |
745 | outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */ | |
746 | } | |
747 | /* foreground color */ | |
748 | outw(GDCIDX, col1 | 0x00); /* set/reset */ | |
749 | e = d; | |
219917ca SW |
750 | f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_height]); |
751 | for (j = 0; j < scp->font_height; ++j, ++f) { | |
984263bc MD |
752 | writeb(e, *f); |
753 | e += line_width; | |
754 | } | |
755 | ++d; | |
756 | if ((i % scp->xsize) == scp->xsize - 1) | |
757 | d += scp->xoff*2 | |
219917ca | 758 | + (scp->font_height - 1)*line_width; |
984263bc MD |
759 | } |
760 | outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ | |
761 | outw(GDCIDX, 0x0000); /* set/reset */ | |
762 | outw(GDCIDX, 0x0001); /* set/reset enable */ | |
763 | } | |
764 | ||
765 | static void | |
766 | vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink) | |
767 | { | |
219917ca | 768 | if (base < 0 || base >= scp->font_height) |
984263bc MD |
769 | return; |
770 | /* the caller may set height <= 0 in order to disable the cursor */ | |
771 | #if 0 | |
772 | scp->cursor_base = base; | |
773 | scp->cursor_height = height; | |
774 | #endif | |
775 | } | |
776 | ||
777 | static void | |
2a85d763 MD |
778 | draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip) |
779 | { | |
a5eb78ad SW |
780 | int line_width, pixel_size, height; |
781 | int a, i, j, k, pos; | |
782 | uint32_t fg, bg, u32; | |
783 | unsigned char *char_data; | |
784 | vm_offset_t draw_pos; | |
2a85d763 MD |
785 | |
786 | line_width = scp->sc->adp->va_line_width; | |
787 | pixel_size = scp->sc->adp->va_info.vi_pixel_size; | |
788 | ||
219917ca SW |
789 | draw_pos = VIDEO_MEMORY_POS(scp, at, scp->font_width * pixel_size) + |
790 | (scp->font_height - scp->cursor_base - 1) * line_width; | |
2a85d763 MD |
791 | |
792 | a = sc_vtb_geta(&scp->vtb, at); | |
793 | ||
794 | if (flip) { | |
a5eb78ad SW |
795 | fg = scp->ega_palette[((on) ? (a & 0x0f00) : |
796 | ((a & 0xf000) >> 4)) >> 8]; | |
797 | bg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) : | |
798 | (a & 0x0f00)) >> 8]; | |
2a85d763 | 799 | } else { |
a5eb78ad SW |
800 | fg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) : |
801 | (a & 0x0f00)) >> 8]; | |
802 | bg = scp->ega_palette[((on) ? (a & 0x0f00) : | |
803 | ((a & 0xf000) >> 4)) >> 8]; | |
2a85d763 MD |
804 | } |
805 | ||
219917ca SW |
806 | char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height + |
807 | scp->font_height - scp->cursor_base - 1]); | |
2a85d763 | 808 | |
219917ca | 809 | height = imin(scp->cursor_height, scp->font_height); |
2a85d763 | 810 | |
a5eb78ad SW |
811 | for (i = 0; i < height; ++i, --char_data) { |
812 | pos = 7; | |
813 | ||
814 | for (j = 0; j < 2 * pixel_size; ++j) { | |
815 | u32 = 0; | |
816 | ||
817 | for (k = 0; k < 4 / pixel_size; ++k) { | |
818 | u32 += (*char_data & (1 << pos--) ? | |
819 | fg : bg) << (k * 8 * pixel_size); | |
820 | } | |
821 | ||
822 | writel(draw_pos, u32); | |
823 | draw_pos += 4; | |
2a85d763 MD |
824 | } |
825 | ||
a5eb78ad | 826 | draw_pos -= line_width + 8 * pixel_size; |
2a85d763 MD |
827 | } |
828 | } | |
829 | ||
771006e1 SW |
830 | static void |
831 | draw_pxlcursor_packed(scr_stat *scp, int at, int on, int flip) | |
832 | { | |
833 | int line_width, height; | |
834 | int a, i; | |
835 | uint32_t fg, bg, u32; | |
836 | unsigned char *char_data; | |
837 | vm_offset_t draw_pos; | |
838 | ||
839 | line_width = scp->sc->adp->va_line_width; | |
840 | ||
841 | draw_pos = VIDEO_MEMORY_POS(scp, at, 8) + | |
219917ca | 842 | (scp->font_height - scp->cursor_base - 1) * line_width; |
771006e1 SW |
843 | |
844 | a = sc_vtb_geta(&scp->vtb, at); | |
845 | ||
846 | if (flip) { | |
847 | fg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8; | |
848 | bg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8; | |
849 | } else { | |
850 | fg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8; | |
851 | bg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8; | |
852 | } | |
853 | ||
219917ca SW |
854 | char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height + |
855 | scp->font_height - scp->cursor_base - 1]); | |
771006e1 | 856 | |
219917ca | 857 | height = imin(scp->cursor_height, scp->font_height); |
771006e1 SW |
858 | |
859 | for (i = 0; i < height; ++i, --char_data) { | |
860 | u32 = ((*char_data & 1 ? fg : bg) << 24) + | |
861 | ((*char_data & 2 ? fg : bg) << 16) + | |
862 | ((*char_data & 4 ? fg : bg) << 8) + | |
863 | (*char_data & 8 ? fg : bg); | |
864 | writel(draw_pos + 4, u32); | |
865 | ||
866 | u32 = ((*char_data & 16 ? fg : bg) << 24) + | |
867 | ((*char_data & 32 ? fg : bg) << 16) + | |
868 | ((*char_data & 64 ? fg : bg) << 8) + | |
869 | (*char_data & 128 ? fg : bg); | |
870 | writel(draw_pos, u32); | |
871 | ||
872 | draw_pos -= line_width; | |
873 | } | |
874 | } | |
875 | ||
2a85d763 MD |
876 | static void |
877 | draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip) | |
984263bc MD |
878 | { |
879 | vm_offset_t d; | |
880 | u_char *f; | |
881 | int line_width; | |
882 | int height; | |
883 | int col; | |
884 | int a; | |
885 | int i; | |
886 | u_char c; | |
887 | ||
888 | line_width = scp->sc->adp->va_line_width; | |
2a85d763 MD |
889 | |
890 | d = VIDEO_MEMORY_POS(scp, at, 1) + | |
219917ca | 891 | (scp->font_height - scp->cursor_base - 1) * line_width; |
984263bc MD |
892 | |
893 | outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ | |
894 | outw(GDCIDX, 0x0003); /* data rotate/function select */ | |
895 | outw(GDCIDX, 0x0f01); /* set/reset enable */ | |
896 | /* set background color in EGA/VGA latch */ | |
897 | a = sc_vtb_geta(&scp->vtb, at); | |
898 | if (flip) | |
899 | col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00); | |
900 | else | |
901 | col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4); | |
902 | outw(GDCIDX, col | 0x00); /* set/reset */ | |
903 | outw(GDCIDX, 0xff08); /* bit mask */ | |
904 | writeb(d, 0); | |
905 | c = readb(d); /* set bg color in the latch */ | |
906 | /* foreground color */ | |
907 | if (flip) | |
908 | col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4); | |
909 | else | |
910 | col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00); | |
911 | outw(GDCIDX, col | 0x00); /* set/reset */ | |
219917ca SW |
912 | f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_height |
913 | + scp->font_height - scp->cursor_base - 1]); | |
914 | height = imin(scp->cursor_height, scp->font_height); | |
984263bc MD |
915 | for (i = 0; i < height; ++i, --f) { |
916 | outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */ | |
917 | writeb(d, 0); | |
918 | d -= line_width; | |
919 | } | |
920 | outw(GDCIDX, 0x0000); /* set/reset */ | |
921 | outw(GDCIDX, 0x0001); /* set/reset enable */ | |
922 | outw(GDCIDX, 0xff08); /* bit mask */ | |
923 | } | |
924 | ||
925 | static int pxlblinkrate = 0; | |
926 | ||
927 | static void | |
2a85d763 MD |
928 | vga_pxlcursor_direct(scr_stat *scp, int at, int blink, int on, int flip) |
929 | { | |
930 | if (scp->cursor_height <= 0) /* the text cursor is disabled */ | |
931 | return; | |
932 | ||
933 | if (on) { | |
934 | if (!blink) { | |
935 | scp->status |= VR_CURSOR_ON; | |
936 | draw_pxlcursor_direct(scp, at, on, flip); | |
937 | } else if (++pxlblinkrate & 4) { | |
938 | pxlblinkrate = 0; | |
939 | scp->status ^= VR_CURSOR_ON; | |
940 | draw_pxlcursor_direct(scp, at, | |
941 | scp->status & VR_CURSOR_ON, | |
942 | flip); | |
943 | } | |
944 | } else { | |
945 | if (scp->status & VR_CURSOR_ON) | |
946 | draw_pxlcursor_direct(scp, at, on, flip); | |
947 | scp->status &= ~VR_CURSOR_ON; | |
948 | } | |
949 | if (blink) | |
950 | scp->status |= VR_CURSOR_BLINK; | |
951 | else | |
952 | scp->status &= ~VR_CURSOR_BLINK; | |
953 | } | |
954 | ||
955 | static void | |
771006e1 SW |
956 | vga_pxlcursor_packed(scr_stat *scp, int at, int blink, int on, int flip) |
957 | { | |
958 | if (scp->cursor_height <= 0) /* the text cursor is disabled */ | |
959 | return; | |
960 | ||
961 | if (on) { | |
962 | if (!blink) { | |
963 | scp->status |= VR_CURSOR_ON; | |
964 | draw_pxlcursor_packed(scp, at, on, flip); | |
965 | } else if (++pxlblinkrate & 4) { | |
966 | pxlblinkrate = 0; | |
967 | scp->status ^= VR_CURSOR_ON; | |
968 | draw_pxlcursor_packed(scp, at, | |
969 | scp->status & VR_CURSOR_ON, | |
970 | flip); | |
971 | } | |
972 | } else { | |
973 | if (scp->status & VR_CURSOR_ON) | |
974 | draw_pxlcursor_packed(scp, at, on, flip); | |
975 | scp->status &= ~VR_CURSOR_ON; | |
976 | } | |
977 | if (blink) | |
978 | scp->status |= VR_CURSOR_BLINK; | |
979 | else | |
980 | scp->status &= ~VR_CURSOR_BLINK; | |
981 | } | |
982 | ||
983 | static void | |
2a85d763 | 984 | vga_pxlcursor_planar(scr_stat *scp, int at, int blink, int on, int flip) |
984263bc MD |
985 | { |
986 | if (scp->cursor_height <= 0) /* the text cursor is disabled */ | |
987 | return; | |
988 | ||
989 | if (on) { | |
990 | if (!blink) { | |
991 | scp->status |= VR_CURSOR_ON; | |
2a85d763 | 992 | draw_pxlcursor_planar(scp, at, on, flip); |
984263bc MD |
993 | } else if (++pxlblinkrate & 4) { |
994 | pxlblinkrate = 0; | |
995 | scp->status ^= VR_CURSOR_ON; | |
2a85d763 MD |
996 | draw_pxlcursor_planar(scp, at, |
997 | scp->status & VR_CURSOR_ON, | |
998 | flip); | |
984263bc MD |
999 | } |
1000 | } else { | |
1001 | if (scp->status & VR_CURSOR_ON) | |
2a85d763 | 1002 | draw_pxlcursor_planar(scp, at, on, flip); |
984263bc MD |
1003 | scp->status &= ~VR_CURSOR_ON; |
1004 | } | |
1005 | if (blink) | |
1006 | scp->status |= VR_CURSOR_BLINK; | |
1007 | else | |
1008 | scp->status &= ~VR_CURSOR_BLINK; | |
1009 | } | |
1010 | ||
1011 | static void | |
2a85d763 | 1012 | vga_pxlblink_direct(scr_stat *scp, int at, int flip) |
984263bc MD |
1013 | { |
1014 | if (!(scp->status & VR_CURSOR_BLINK)) | |
1015 | return; | |
1016 | if (!(++pxlblinkrate & 4)) | |
1017 | return; | |
1018 | pxlblinkrate = 0; | |
1019 | scp->status ^= VR_CURSOR_ON; | |
2a85d763 MD |
1020 | draw_pxlcursor_direct(scp, at, scp->status & VR_CURSOR_ON, flip); |
1021 | } | |
1022 | ||
771006e1 SW |
1023 | static void |
1024 | vga_pxlblink_packed(scr_stat *scp, int at, int flip) | |
1025 | { | |
1026 | if (!(scp->status & VR_CURSOR_BLINK)) | |
1027 | return; | |
1028 | if (!(++pxlblinkrate & 4)) | |
1029 | return; | |
1030 | pxlblinkrate = 0; | |
1031 | scp->status ^= VR_CURSOR_ON; | |
1032 | draw_pxlcursor_packed(scp, at, scp->status & VR_CURSOR_ON, flip); | |
1033 | } | |
1034 | ||
2a85d763 MD |
1035 | static void |
1036 | vga_pxlblink_planar(scr_stat *scp, int at, int flip) | |
1037 | { | |
1038 | if (!(scp->status & VR_CURSOR_BLINK)) | |
1039 | return; | |
1040 | if (!(++pxlblinkrate & 4)) | |
1041 | return; | |
1042 | pxlblinkrate = 0; | |
1043 | scp->status ^= VR_CURSOR_ON; | |
1044 | draw_pxlcursor_planar(scp, at, scp->status & VR_CURSOR_ON, flip); | |
984263bc MD |
1045 | } |
1046 | ||
1047 | #ifndef SC_NO_CUTPASTE | |
1048 | ||
a5eb78ad SW |
1049 | static void |
1050 | draw_pxlmouse_direct(scr_stat *scp, int x, int y) | |
1051 | { | |
1052 | int line_width, pixel_size; | |
1053 | int xend, yend; | |
1054 | int i, j; | |
1055 | vm_offset_t draw_pos; | |
1056 | ||
1057 | line_width = scp->sc->adp->va_line_width; | |
1058 | pixel_size = scp->sc->adp->va_info.vi_pixel_size; | |
1059 | ||
1060 | xend = imin(x + 8, 8 * (scp->xoff + scp->xsize)); | |
219917ca | 1061 | yend = imin(y + 16, scp->font_height * (scp->yoff + scp->ysize)); |
a5eb78ad SW |
1062 | |
1063 | draw_pos = scp->sc->adp->va_window + y * line_width + x * pixel_size; | |
1064 | ||
1065 | for (i = 0; i < (yend - y); i++) { | |
1066 | for (j = (xend - x - 1); j >= 0; j--) { | |
1067 | switch (scp->sc->adp->va_info.vi_depth) { | |
1068 | case 32: | |
1069 | if (mouse_or_mask[i] & 1 << (15 - j)) | |
1070 | writel(draw_pos + 4 * j, | |
1071 | scp->ega_palette[15]); | |
1072 | else if (mouse_and_mask[i] & 1 << (15 - j)) | |
1073 | writel(draw_pos + 4 * j, | |
1074 | scp->ega_palette[0]); | |
1075 | break; | |
1076 | case 16: | |
1077 | /* FALLTHROUGH */ | |
1078 | case 15: | |
1079 | if (mouse_or_mask[i] & 1 << (15 - j)) | |
1080 | writew(draw_pos + 2 * j, | |
1081 | scp->ega_palette[15]); | |
1082 | else if (mouse_and_mask[i] & 1 << (15 - j)) | |
1083 | writew(draw_pos + 2 * j, | |
1084 | scp->ega_palette[0]); | |
1085 | break; | |
1086 | } | |
1087 | } | |
1088 | ||
1089 | draw_pos += line_width; | |
1090 | } | |
1091 | } | |
1092 | ||
771006e1 SW |
1093 | static void |
1094 | draw_pxlmouse_packed(scr_stat *scp, int x, int y) | |
1095 | { | |
1096 | int line_width; | |
1097 | int xend, yend; | |
1098 | int i, j; | |
1099 | vm_offset_t draw_pos; | |
1100 | ||
1101 | line_width = scp->sc->adp->va_line_width; | |
1102 | ||
219917ca SW |
1103 | xend = imin(scp->font_width * (scp->xoff + scp->xsize), |
1104 | imin(x + 16, scp->xpixel)); | |
1105 | yend = imin(scp->font_height * (scp->yoff + scp->ysize), | |
1106 | imin(y + 16, scp->ypixel)); | |
771006e1 SW |
1107 | |
1108 | draw_pos = scp->sc->adp->va_window + y * line_width + x; | |
1109 | ||
1110 | for (i = 0; i < (yend - y); i++) { | |
1111 | for (j = (xend - x - 1); j >= 0; j--) { | |
1112 | if (mouse_or_mask[i] & 1 << (15 - j)) | |
1113 | writeb(draw_pos + j, 15); | |
1114 | else if (mouse_and_mask[i] & 1 << (15 - j)) | |
1115 | writeb(draw_pos + j, 0); | |
1116 | } | |
1117 | ||
1118 | draw_pos += line_width; | |
1119 | } | |
1120 | } | |
1121 | ||
984263bc | 1122 | static void |
2a85d763 | 1123 | draw_pxlmouse_planar(scr_stat *scp, int x, int y) |
984263bc MD |
1124 | { |
1125 | vm_offset_t p; | |
1126 | int line_width; | |
03c040a2 | 1127 | int xoff; |
984263bc MD |
1128 | int ymax; |
1129 | u_short m; | |
1130 | int i, j; | |
1131 | ||
1132 | line_width = scp->sc->adp->va_line_width; | |
1133 | xoff = (x - scp->xoff*8)%8; | |
219917ca | 1134 | ymax = imin(y + 16, scp->font_height * (scp->yoff + scp->ysize)); |
984263bc MD |
1135 | |
1136 | outw(GDCIDX, 0x0805); /* read mode 1, write mode 0 */ | |
1137 | outw(GDCIDX, 0x0001); /* set/reset enable */ | |
1138 | outw(GDCIDX, 0x0002); /* color compare */ | |
1139 | outw(GDCIDX, 0x0007); /* color don't care */ | |
1140 | outw(GDCIDX, 0xff08); /* bit mask */ | |
1141 | outw(GDCIDX, 0x0803); /* data rotate/function select (and) */ | |
1142 | p = scp->sc->adp->va_window + line_width*y + x/8; | |
5fa98c1e | 1143 | if (x < 8 * (scp->xoff + scp->xsize) - 8) { |
984263bc MD |
1144 | for (i = y, j = 0; i < ymax; ++i, ++j) { |
1145 | m = ~(mouse_and_mask[j] >> xoff); | |
984263bc MD |
1146 | *(u_char *)p &= m >> 8; |
1147 | *(u_char *)(p + 1) &= m; | |
984263bc MD |
1148 | p += line_width; |
1149 | } | |
1150 | } else { | |
1151 | xoff += 8; | |
1152 | for (i = y, j = 0; i < ymax; ++i, ++j) { | |
1153 | m = ~(mouse_and_mask[j] >> xoff); | |
984263bc | 1154 | *(u_char *)p &= m; |
984263bc MD |
1155 | p += line_width; |
1156 | } | |
1157 | } | |
1158 | outw(GDCIDX, 0x1003); /* data rotate/function select (or) */ | |
1159 | p = scp->sc->adp->va_window + line_width*y + x/8; | |
5fa98c1e | 1160 | if (x < 8 * (scp->xoff + scp->xsize) - 8) { |
984263bc MD |
1161 | for (i = y, j = 0; i < ymax; ++i, ++j) { |
1162 | m = mouse_or_mask[j] >> xoff; | |
984263bc MD |
1163 | *(u_char *)p &= m >> 8; |
1164 | *(u_char *)(p + 1) &= m; | |
984263bc MD |
1165 | p += line_width; |
1166 | } | |
1167 | } else { | |
1168 | for (i = y, j = 0; i < ymax; ++i, ++j) { | |
1169 | m = mouse_or_mask[j] >> xoff; | |
984263bc | 1170 | *(u_char *)p &= m; |
984263bc MD |
1171 | p += line_width; |
1172 | } | |
1173 | } | |
1174 | outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ | |
1175 | outw(GDCIDX, 0x0003); /* data rotate/function select */ | |
1176 | } | |
1177 | ||
1178 | static void | |
a5eb78ad | 1179 | remove_pxlmouse(scr_stat *scp, int x, int y) |
984263bc | 1180 | { |
984263bc MD |
1181 | int col, row; |
1182 | int pos; | |
984263bc MD |
1183 | int i; |
1184 | ||
1185 | /* erase the mouse cursor image */ | |
219917ca SW |
1186 | col = x / scp->font_width - scp->xoff; |
1187 | row = y / scp->font_height - scp->yoff; | |
1188 | pos = row * scp->xsize + col; | |
984263bc | 1189 | i = (col < scp->xsize - 1) ? 2 : 1; |
7ae6dbf0 | 1190 | (*scp->rndr->draw)(scp, pos, i, FALSE); |
984263bc | 1191 | if (row < scp->ysize - 1) |
7ae6dbf0 | 1192 | (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE); |
984263bc MD |
1193 | } |
1194 | ||
1195 | static void | |
2a85d763 MD |
1196 | vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on) |
1197 | { | |
a5eb78ad SW |
1198 | if (on) |
1199 | draw_pxlmouse_direct(scp, x, y); | |
1200 | else | |
1201 | remove_pxlmouse(scp, x, y); | |
2a85d763 MD |
1202 | } |
1203 | ||
771006e1 SW |
1204 | static void |
1205 | vga_pxlmouse_packed(scr_stat *scp, int x, int y, int on) | |
1206 | { | |
1207 | if (on) | |
1208 | draw_pxlmouse_packed(scp, x, y); | |
1209 | else | |
1210 | remove_pxlmouse(scp, x, y); | |
1211 | } | |
1212 | ||
2a85d763 MD |
1213 | static void |
1214 | vga_pxlmouse_planar(scr_stat *scp, int x, int y, int on) | |
984263bc MD |
1215 | { |
1216 | if (on) | |
2a85d763 | 1217 | draw_pxlmouse_planar(scp, x, y); |
984263bc | 1218 | else |
a5eb78ad | 1219 | remove_pxlmouse(scp, x, y); |
984263bc MD |
1220 | } |
1221 | ||
1222 | #endif /* SC_NO_CUTPASTE */ | |
1223 | #endif /* SC_PIXEL_MODE */ | |
1224 | ||
1225 | #ifndef SC_NO_MODE_CHANGE | |
1226 | ||
1227 | /* graphics mode renderer */ | |
1228 | ||
1229 | static void | |
1230 | vga_grborder(scr_stat *scp, int color) | |
1231 | { | |
2efb75f3 | 1232 | lwkt_gettoken(&vga_token); |
984263bc | 1233 | (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color); |
2efb75f3 | 1234 | lwkt_reltoken(&vga_token); |
984263bc MD |
1235 | } |
1236 | ||
1237 | #endif |