2 * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * @OSF_FREE_COPYRIGHT@
33 * @APPLE_FREE_COPYRIGHT@
36 * NetBSD: ite.c,v 1.16 1995/07/17 01:24:34 briggs Exp
38 * Copyright (c) 1988 University of Utah.
39 * Copyright (c) 1990, 1993
40 * The Regents of the University of California. All rights reserved.
42 * This code is derived from software contributed to Berkeley by
43 * the Systems Programming Group of the University of Utah Computer
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
49 * 1. Redistributions of source code must retain the above copyright
50 * notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright
52 * notice, this list of conditions and the following disclaimer in the
53 * documentation and/or other materials provided with the distribution.
54 * 3. All advertising materials mentioning features or use of this software
55 * must display the following acknowledgement:
56 * This product includes software developed by the University of
57 * California, Berkeley and its contributors.
58 * 4. Neither the name of the University nor the names of its contributors
59 * may be used to endorse or promote products derived from this software
60 * without specific prior written permission.
62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
74 * from: Utah $Hdr: ite.c 1.28 92/12/20$
76 * @(#)ite.c 8.2 (Berkeley) 1/12/94
82 * The ite module handles the system console; that is, stuff printed
83 * by the kernel and by user programs while "desktop" and X aren't
84 * running. Some (very small) parts are based on hp300's 4.4 ite.c,
85 * hence the above copyright.
87 * -- Brad and Lawrence, June 26th, 1994
93 #include <console/video_console.h>
94 #include <console/serial_protos.h>
96 #include <kern/kern_types.h>
97 #include <kern/kalloc.h>
98 #include <kern/debug.h>
99 #include <kern/lock.h>
100 #include <kern/spl.h>
101 #include <kern/thread_call.h>
104 #include <vm/vm_kern.h>
105 #include <machine/io_map_entries.h>
106 #include <machine/machine_cpu.h>
108 #include <pexpert/pexpert.h>
109 #include <sys/kdebug.h>
111 #include "iso_font.c"
113 #include "progress_meter_data.c"
116 #include "sys/msgbuf.h"
119 * Generic Console (Front-End)
120 * ---------------------------
123 struct vc_info vinfo
;
124 /* if panicDialogDesired is true then we use the panic dialog when its */
125 /* allowed otherwise we won't use the panic dialog even if it is allowed */
126 boolean_t panicDialogDesired
;
128 void noroot_icon_test(void);
131 extern int disableConsoleOutput
;
132 static boolean_t gc_enabled
= FALSE
;
133 static boolean_t gc_initialized
= FALSE
;
134 static boolean_t vm_initialized
= FALSE
;
137 void (*initialize
)(struct vc_info
* info
);
138 void (*enable
)(boolean_t enable
);
139 void (*paint_char
)(unsigned int xx
, unsigned int yy
, unsigned char ch
,
140 int attrs
, unsigned char ch_previous
,
142 void (*clear_screen
)(unsigned int xx
, unsigned int yy
, unsigned int top
,
143 unsigned int bottom
, int which
);
144 void (*scroll_down
)(int num
, unsigned int top
, unsigned int bottom
);
145 void (*scroll_up
)(int num
, unsigned int top
, unsigned int bottom
);
146 void (*hide_cursor
)(unsigned int xx
, unsigned int yy
);
147 void (*show_cursor
)(unsigned int xx
, unsigned int yy
);
148 void (*update_color
)(int color
, boolean_t fore
);
151 static unsigned char *gc_buffer_attributes
;
152 static unsigned char *gc_buffer_characters
;
153 static unsigned char *gc_buffer_colorcodes
;
154 static unsigned char *gc_buffer_tab_stops
;
155 static uint32_t gc_buffer_columns
;
156 static uint32_t gc_buffer_rows
;
157 static uint32_t gc_buffer_size
;
159 #if defined(__i386__) || defined(__x86_64__)
160 decl_simple_lock_data(static, vcputc_lock
);
162 #define VCPUTC_LOCK_INIT() \
164 simple_lock_init(&vcputc_lock, 0); \
167 #define VCPUTC_LOCK_LOCK() \
169 boolean_t istate = ml_get_interrupts_enabled(); \
170 while (!simple_lock_try(&vcputc_lock)) \
173 handle_pending_TLB_flushes(); \
178 #define VCPUTC_LOCK_UNLOCK() \
180 simple_unlock(&vcputc_lock); \
183 static hw_lock_data_t vcputc_lock
;
185 #define VCPUTC_LOCK_INIT() \
187 hw_lock_init(&vcputc_lock); \
190 #define VCPUTC_LOCK_LOCK() \
192 if (!hw_lock_to(&vcputc_lock, hwLockTimeOut*10))\
194 panic("VCPUTC_LOCK_LOCK"); \
198 #define VCPUTC_LOCK_UNLOCK() \
200 hw_lock_unlock(&vcputc_lock); \
206 # 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
208 # 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
209 # Background color codes:
210 # 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
216 #define ATTR_REVERSE 4
218 #define COLOR_BACKGROUND 0
219 #define COLOR_FOREGROUND 7
221 #define COLOR_CODE_GET(code, fore) (((code) & ((fore) ? 0xF0 : 0x0F)) >> ((fore) ? 4 : 0))
222 #define COLOR_CODE_SET(code, color, fore) (((code) & ((fore) ? 0x0F : 0xF0)) | ((color) << ((fore) ? 4 : 0)))
224 static unsigned char gc_color_code
;
228 static unsigned int gc_x
, gc_y
, gc_savex
, gc_savey
;
229 static unsigned int gc_par
[MAXPARS
], gc_numpars
, gc_hanging_cursor
, gc_attr
, gc_saveattr
;
231 /* VT100 scroll region */
232 static unsigned int gc_scrreg_top
, gc_scrreg_bottom
;
235 ESnormal
, /* Nothing yet */
237 ESsquare
, /* Got ESC [ */
238 ESgetpars
, /* About to get or getting the parameters */
239 ESgotpars
, /* Finished getting the parameters */
240 ESfunckey
, /* Function key */
241 EShash
, /* DEC-specific stuff (screen align, etc.) */
242 ESsetG0
, /* Specify the G0 character set */
243 ESsetG1
, /* Specify the G1 character set */
246 ESignore
/* Ignore this sequence */
247 } gc_vt100state
= ESnormal
;
250 #ifdef CONFIG_VC_PROGRESS_WHITE
251 enum { kProgressAcquireDelay
= 0 /* secs */ };
253 enum { kProgressAcquireDelay
= 5 /* secs */ };
256 static int8_t vc_rotate_matr
[4][2][2] = {
267 static int gc_wrap_mode
= 1, gc_relative_origin
= 0;
268 static int gc_charset_select
= 0, gc_save_charset_s
= 0;
269 static int gc_charset
[2] = { 0, 0 };
270 static int gc_charset_save
[2] = { 0, 0 };
272 static void gc_clear_line(unsigned int xx
, unsigned int yy
, int which
);
273 static void gc_clear_screen(unsigned int xx
, unsigned int yy
, int top
,
274 unsigned int bottom
, int which
);
275 static void gc_enable(boolean_t enable
);
276 static void gc_hide_cursor(unsigned int xx
, unsigned int yy
);
277 static void gc_initialize(struct vc_info
* info
);
278 static boolean_t
gc_is_tab_stop(unsigned int column
);
279 static void gc_paint_char(unsigned int xx
, unsigned int yy
, unsigned char ch
,
281 static void gc_putchar(char ch
);
282 static void gc_putc_askcmd(unsigned char ch
);
283 static void gc_putc_charsetcmd(int charset
, unsigned char ch
);
284 static void gc_putc_charsizecmd(unsigned char ch
);
285 static void gc_putc_esc(unsigned char ch
);
286 static void gc_putc_getpars(unsigned char ch
);
287 static void gc_putc_gotpars(unsigned char ch
);
288 static void gc_putc_normal(unsigned char ch
);
289 static void gc_putc_square(unsigned char ch
);
290 static void gc_reset_screen(void);
291 static void gc_reset_tabs(void);
292 static void gc_reset_vt100(void);
293 static void gc_scroll_down(int num
, unsigned int top
, unsigned int bottom
);
294 static void gc_scroll_up(int num
, unsigned int top
, unsigned int bottom
);
295 static void gc_set_tab_stop(unsigned int column
, boolean_t enabled
);
296 static void gc_show_cursor(unsigned int xx
, unsigned int yy
);
297 static void gc_update_color(int color
, boolean_t fore
);
300 gc_clear_line(unsigned int xx
, unsigned int yy
, int which
)
302 unsigned int start
, end
, i
;
305 * This routine runs extremely slowly. I don't think it's
306 * used all that often, except for To end of line. I'll go
307 * back and speed this up when I speed up the whole vc
312 case 0: /* To end of line */
314 end
= vinfo
.v_columns
-1;
316 case 1: /* To start of line */
320 case 2: /* Whole line */
322 end
= vinfo
.v_columns
-1;
328 for (i
= start
; i
<= end
; i
++) {
329 gc_paint_char(i
, yy
, ' ', ATTR_NONE
);
334 gc_clear_screen(unsigned int xx
, unsigned int yy
, int top
, unsigned int bottom
,
337 if (!gc_buffer_size
) return;
339 if ( xx
< gc_buffer_columns
&& yy
< gc_buffer_rows
&& bottom
<= gc_buffer_rows
)
344 case 0: /* To end of screen */
345 start
= (yy
* gc_buffer_columns
) + xx
;
346 end
= (bottom
* gc_buffer_columns
) - 1;
348 case 1: /* To start of screen */
349 start
= (top
* gc_buffer_columns
);
350 end
= (yy
* gc_buffer_columns
) + xx
;
352 case 2: /* Whole screen */
353 start
= (top
* gc_buffer_columns
);
354 end
= (bottom
* gc_buffer_columns
) - 1;
362 memset(gc_buffer_attributes
+ start
, ATTR_NONE
, end
- start
+ 1);
363 memset(gc_buffer_characters
+ start
, ' ', end
- start
+ 1);
364 memset(gc_buffer_colorcodes
+ start
, gc_color_code
, end
- start
+ 1);
367 gc_ops
.clear_screen(xx
, yy
, top
, bottom
, which
);
371 gc_enable( boolean_t enable
)
373 unsigned char *buffer_attributes
= NULL
;
374 unsigned char *buffer_characters
= NULL
;
375 unsigned char *buffer_colorcodes
= NULL
;
376 unsigned char *buffer_tab_stops
= NULL
;
377 uint32_t buffer_columns
= 0;
378 uint32_t buffer_rows
= 0;
379 uint32_t buffer_size
= 0;
382 if ( enable
== FALSE
)
384 // only disable console output if it goes to the graphics console
385 if ( console_is_serial() == FALSE
)
386 disableConsoleOutput
= TRUE
;
388 gc_ops
.enable(FALSE
);
394 if ( gc_buffer_size
)
396 buffer_attributes
= gc_buffer_attributes
;
397 buffer_characters
= gc_buffer_characters
;
398 buffer_colorcodes
= gc_buffer_colorcodes
;
399 buffer_tab_stops
= gc_buffer_tab_stops
;
400 buffer_columns
= gc_buffer_columns
;
401 buffer_rows
= gc_buffer_rows
;
402 buffer_size
= gc_buffer_size
;
404 gc_buffer_attributes
= NULL
;
405 gc_buffer_characters
= NULL
;
406 gc_buffer_colorcodes
= NULL
;
407 gc_buffer_tab_stops
= NULL
;
408 gc_buffer_columns
= 0;
412 VCPUTC_LOCK_UNLOCK( );
415 kfree( buffer_attributes
, buffer_size
);
416 kfree( buffer_characters
, buffer_size
);
417 kfree( buffer_colorcodes
, buffer_size
);
418 kfree( buffer_tab_stops
, buffer_columns
);
422 VCPUTC_LOCK_UNLOCK( );
428 if ( vm_initialized
)
430 buffer_columns
= vinfo
.v_columns
;
431 buffer_rows
= vinfo
.v_rows
;
432 buffer_size
= buffer_columns
* buffer_rows
;
436 buffer_attributes
= (unsigned char *) kalloc( buffer_size
);
437 buffer_characters
= (unsigned char *) kalloc( buffer_size
);
438 buffer_colorcodes
= (unsigned char *) kalloc( buffer_size
);
439 buffer_tab_stops
= (unsigned char *) kalloc( buffer_columns
);
441 if ( buffer_attributes
== NULL
||
442 buffer_characters
== NULL
||
443 buffer_colorcodes
== NULL
||
444 buffer_tab_stops
== NULL
)
446 if ( buffer_attributes
) kfree( buffer_attributes
, buffer_size
);
447 if ( buffer_characters
) kfree( buffer_characters
, buffer_size
);
448 if ( buffer_colorcodes
) kfree( buffer_colorcodes
, buffer_size
);
449 if ( buffer_tab_stops
) kfree( buffer_tab_stops
, buffer_columns
);
457 memset( buffer_attributes
, ATTR_NONE
, buffer_size
);
458 memset( buffer_characters
, ' ', buffer_size
);
459 memset( buffer_colorcodes
, COLOR_CODE_SET( 0, COLOR_FOREGROUND
, TRUE
), buffer_size
);
460 memset( buffer_tab_stops
, 0, buffer_columns
);
468 gc_buffer_attributes
= buffer_attributes
;
469 gc_buffer_characters
= buffer_characters
;
470 gc_buffer_colorcodes
= buffer_colorcodes
;
471 gc_buffer_tab_stops
= buffer_tab_stops
;
472 gc_buffer_columns
= buffer_columns
;
473 gc_buffer_rows
= buffer_rows
;
474 gc_buffer_size
= buffer_size
;
478 VCPUTC_LOCK_UNLOCK( );
481 gc_ops
.clear_screen(gc_x
, gc_y
, 0, vinfo
.v_rows
, 2);
482 gc_ops
.show_cursor(gc_x
, gc_y
);
486 disableConsoleOutput
= FALSE
;
491 gc_hide_cursor(unsigned int xx
, unsigned int yy
)
493 if ( xx
< gc_buffer_columns
&& yy
< gc_buffer_rows
)
495 uint32_t index
= (yy
* gc_buffer_columns
) + xx
;
496 unsigned char attribute
= gc_buffer_attributes
[index
];
497 unsigned char character
= gc_buffer_characters
[index
];
498 unsigned char colorcode
= gc_buffer_colorcodes
[index
];
499 unsigned char colorcodesave
= gc_color_code
;
501 gc_update_color(COLOR_CODE_GET(colorcode
, TRUE
), TRUE
);
502 gc_update_color(COLOR_CODE_GET(colorcode
, FALSE
), FALSE
);
504 gc_ops
.paint_char(xx
, yy
, character
, attribute
, 0, 0);
506 gc_update_color(COLOR_CODE_GET(colorcodesave
, TRUE
), TRUE
);
507 gc_update_color(COLOR_CODE_GET(colorcodesave
, FALSE
), FALSE
);
511 gc_ops
.hide_cursor(xx
, yy
);
516 gc_initialize(struct vc_info
* info
)
518 if ( gc_initialized
== FALSE
)
523 gc_initialized
= TRUE
;
526 gc_ops
.initialize(info
);
533 gc_paint_char(unsigned int xx
, unsigned int yy
, unsigned char ch
, int attrs
)
535 if ( xx
< gc_buffer_columns
&& yy
< gc_buffer_rows
)
537 uint32_t index
= (yy
* gc_buffer_columns
) + xx
;
539 gc_buffer_attributes
[index
] = attrs
;
540 gc_buffer_characters
[index
] = ch
;
541 gc_buffer_colorcodes
[index
] = gc_color_code
;
544 gc_ops
.paint_char(xx
, yy
, ch
, attrs
, 0, 0);
551 return; /* ignore null characters */
553 switch (gc_vt100state
) {
554 default:gc_vt100state
= ESnormal
; /* FALLTHROUGH */
574 gc_putc_charsizecmd(ch
);
577 gc_putc_charsetcmd(0, ch
);
580 gc_putc_charsetcmd(1, ch
);
584 if (gc_x
>= vinfo
.v_columns
) {
585 if (0 == vinfo
.v_columns
)
588 gc_x
= vinfo
.v_columns
- 1;
590 if (gc_y
>= vinfo
.v_rows
) {
591 if (0 == vinfo
.v_rows
)
594 gc_y
= vinfo
.v_rows
- 1;
599 gc_putc_askcmd(unsigned char ch
)
601 if (ch
>= '0' && ch
<= '9') {
602 gc_par
[gc_numpars
] = (10*gc_par
[gc_numpars
]) + (ch
-'0');
605 gc_vt100state
= ESnormal
;
609 gc_relative_origin
= ch
== 'h';
611 case 7: /* wrap around mode h=1, l=0*/
612 gc_wrap_mode
= ch
== 'h';
621 gc_putc_charsetcmd(int charset
, unsigned char ch
)
623 gc_vt100state
= ESnormal
;
629 gc_charset
[charset
] = 0;
631 case '0' : /* Graphic characters */
633 gc_charset
[charset
] = 0x21;
640 gc_putc_charsizecmd(unsigned char ch
)
642 gc_vt100state
= ESnormal
;
650 case '8' : /* fill 'E's */
653 for (yy
= 0; yy
< vinfo
.v_rows
; yy
++)
654 for (xx
= 0; xx
< vinfo
.v_columns
; xx
++)
655 gc_paint_char(xx
, yy
, 'E', ATTR_NONE
);
663 gc_putc_esc(unsigned char ch
)
665 gc_vt100state
= ESnormal
;
669 gc_vt100state
= ESsquare
;
671 case 'c': /* Reset terminal */
673 gc_clear_screen(gc_x
, gc_y
, 0, vinfo
.v_rows
, 2);
676 case 'D': /* Line feed */
678 if (gc_y
>= gc_scrreg_bottom
-1) {
679 gc_scroll_up(1, gc_scrreg_top
, gc_scrreg_bottom
);
680 gc_y
= gc_scrreg_bottom
- 1;
684 if (ch
== 'E') gc_x
= 0;
686 case 'H': /* Set tab stop */
687 gc_set_tab_stop(gc_x
, TRUE
);
689 case 'M': /* Cursor up */
690 if (gc_y
<= gc_scrreg_top
) {
691 gc_scroll_down(1, gc_scrreg_top
, gc_scrreg_bottom
);
692 gc_y
= gc_scrreg_top
;
700 case '7': /* Save cursor */
703 gc_saveattr
= gc_attr
;
704 gc_save_charset_s
= gc_charset_select
;
705 gc_charset_save
[0] = gc_charset
[0];
706 gc_charset_save
[1] = gc_charset
[1];
708 case '8': /* Restore cursor */
711 gc_attr
= gc_saveattr
;
712 gc_charset_select
= gc_save_charset_s
;
713 gc_charset
[0] = gc_charset_save
[0];
714 gc_charset
[1] = gc_charset_save
[1];
716 case 'Z': /* return terminal ID */
718 case '#': /* change characters height */
719 gc_vt100state
= EScharsize
;
722 gc_vt100state
= ESsetG0
;
724 case ')': /* character set sequence */
725 gc_vt100state
= ESsetG1
;
730 /* Rest not supported */
737 gc_putc_getpars(unsigned char ch
)
740 gc_vt100state
= ESask
;
744 gc_vt100state
= ESnormal
;
748 if (ch
== ';' && gc_numpars
< MAXPARS
- 1) {
751 if (ch
>= '0' && ch
<= '9') {
752 gc_par
[gc_numpars
] *= 10;
753 gc_par
[gc_numpars
] += ch
- '0';
756 gc_vt100state
= ESgotpars
;
762 gc_putc_gotpars(unsigned char ch
)
767 /* special case for vttest for handling cursor
768 movement in escape sequences */
770 gc_vt100state
= ESgotpars
;
773 gc_vt100state
= ESnormal
;
776 gc_y
-= gc_par
[0] ? gc_par
[0] : 1;
777 if (gc_y
< gc_scrreg_top
)
778 gc_y
= gc_scrreg_top
;
781 gc_y
+= gc_par
[0] ? gc_par
[0] : 1;
782 if (gc_y
>= gc_scrreg_bottom
)
783 gc_y
= gc_scrreg_bottom
- 1;
785 case 'C': /* Right */
786 gc_x
+= gc_par
[0] ? gc_par
[0] : 1;
787 if (gc_x
>= vinfo
.v_columns
)
788 gc_x
= vinfo
.v_columns
-1;
791 if (gc_par
[0] > gc_x
)
798 case 'H': /* Set cursor position */
800 gc_x
= gc_par
[1] ? gc_par
[1] - 1 : 0;
801 gc_y
= gc_par
[0] ? gc_par
[0] - 1 : 0;
802 if (gc_relative_origin
)
803 gc_y
+= gc_scrreg_top
;
804 gc_hanging_cursor
= 0;
806 case 'X': /* clear p1 characters */
808 for (i
= gc_x
; i
< gc_x
+ gc_par
[0]; i
++)
809 gc_paint_char(i
, gc_y
, ' ', ATTR_NONE
);
812 case 'J': /* Clear part of screen */
813 gc_clear_screen(gc_x
, gc_y
, 0, vinfo
.v_rows
, gc_par
[0]);
815 case 'K': /* Clear part of line */
816 gc_clear_line(gc_x
, gc_y
, gc_par
[0]);
818 case 'g': /* tab stops */
821 case 2: /* reset tab stops */
822 /* gc_reset_tabs(); */
824 case 3: /* Clear every tabs */
826 for (i
= 0; i
<= vinfo
.v_columns
; i
++)
827 gc_set_tab_stop(i
, FALSE
);
831 gc_set_tab_stop(gc_x
, FALSE
);
835 case 'm': /* Set attribute */
836 for (i
= 0; i
< gc_numpars
; i
++) {
840 gc_update_color(COLOR_BACKGROUND
, FALSE
);
841 gc_update_color(COLOR_FOREGROUND
, TRUE
);
844 gc_attr
|= ATTR_BOLD
;
847 gc_attr
|= ATTR_UNDER
;
850 gc_attr
|= ATTR_REVERSE
;
853 gc_attr
&= ~ATTR_BOLD
;
856 gc_attr
&= ~ATTR_UNDER
;
859 gc_attr
&= ~ATTR_REVERSE
;
862 case 25: /* blink/no blink */
865 if (gc_par
[i
] >= 30 && gc_par
[i
] <= 37)
866 gc_update_color(gc_par
[i
] - 30, TRUE
);
867 if (gc_par
[i
] >= 40 && gc_par
[i
] <= 47)
868 gc_update_color(gc_par
[i
] - 40, FALSE
);
873 case 'r': /* Set scroll region */
875 /* ensure top < bottom, and both within limits */
876 if ((gc_numpars
> 0) && (gc_par
[0] < vinfo
.v_rows
)) {
877 gc_scrreg_top
= gc_par
[0] ? gc_par
[0] - 1 : 0;
881 if ((gc_numpars
> 1) && (gc_par
[1] <= vinfo
.v_rows
) && (gc_par
[1] > gc_par
[0])) {
882 gc_scrreg_bottom
= gc_par
[1];
883 if (gc_scrreg_bottom
> vinfo
.v_rows
)
884 gc_scrreg_bottom
= vinfo
.v_rows
;
886 gc_scrreg_bottom
= vinfo
.v_rows
;
888 if (gc_relative_origin
)
889 gc_y
= gc_scrreg_top
;
896 gc_putc_normal(unsigned char ch
)
899 case '\a': /* Beep */
901 case 127: /* Delete */
902 case '\b': /* Backspace */
903 if (gc_hanging_cursor
) {
904 gc_hanging_cursor
= 0;
911 if (gc_buffer_tab_stops
) while (gc_x
< vinfo
.v_columns
&& !gc_is_tab_stop(++gc_x
));
913 if (gc_x
>= vinfo
.v_columns
)
914 gc_x
= vinfo
.v_columns
-1;
918 case '\n': /* Line feed */
919 if (gc_y
>= gc_scrreg_bottom
-1 ) {
920 gc_scroll_up(1, gc_scrreg_top
, gc_scrreg_bottom
);
921 gc_y
= gc_scrreg_bottom
- 1;
926 case '\r': /* Carriage return */
928 gc_hanging_cursor
= 0;
930 case 0x0e: /* Select G1 charset (Control-N) */
931 gc_charset_select
= 1;
933 case 0x0f: /* Select G0 charset (Control-O) */
934 gc_charset_select
= 0;
936 case 0x18 : /* CAN : cancel */
937 case 0x1A : /* like cancel */
938 /* well, i do nothing here, may be later */
940 case '\033': /* Escape */
941 gc_vt100state
= ESesc
;
942 gc_hanging_cursor
= 0;
946 if (gc_hanging_cursor
) {
948 if (gc_y
>= gc_scrreg_bottom
-1 ) {
949 gc_scroll_up(1, gc_scrreg_top
, gc_scrreg_bottom
);
950 gc_y
= gc_scrreg_bottom
- 1;
954 gc_hanging_cursor
= 0;
956 gc_paint_char(gc_x
, gc_y
, (ch
>= 0x60 && ch
<= 0x7f) ? ch
+ gc_charset
[gc_charset_select
]
958 if (gc_x
== vinfo
.v_columns
- 1) {
959 gc_hanging_cursor
= gc_wrap_mode
;
970 gc_putc_square(unsigned char ch
)
974 for (i
= 0; i
< MAXPARS
; i
++) {
979 gc_vt100state
= ESgetpars
;
986 gc_reset_screen(void)
997 if (!gc_buffer_tab_stops
) return;
999 for (i
= 0; i
< vinfo
.v_columns
; i
++) {
1000 gc_buffer_tab_stops
[i
] = ((i
% 8) == 0);
1006 gc_set_tab_stop(unsigned int column
, boolean_t enabled
)
1008 if (gc_buffer_tab_stops
&& (column
< vinfo
.v_columns
)) {
1009 gc_buffer_tab_stops
[column
] = enabled
;
1013 static boolean_t
gc_is_tab_stop(unsigned int column
)
1015 if (gc_buffer_tab_stops
== NULL
)
1016 return ((column
% 8) == 0);
1017 if (column
< vinfo
.v_columns
)
1018 return gc_buffer_tab_stops
[column
];
1024 gc_reset_vt100(void)
1028 gc_scrreg_bottom
= vinfo
.v_rows
;
1029 gc_attr
= ATTR_NONE
;
1030 gc_charset
[0] = gc_charset
[1] = 0;
1031 gc_charset_select
= 0;
1033 gc_relative_origin
= 0;
1034 gc_update_color(COLOR_BACKGROUND
, FALSE
);
1035 gc_update_color(COLOR_FOREGROUND
, TRUE
);
1039 gc_scroll_down(int num
, unsigned int top
, unsigned int bottom
)
1041 if (!gc_buffer_size
) return;
1043 if ( bottom
<= gc_buffer_rows
)
1045 unsigned char colorcodesave
= gc_color_code
;
1046 uint32_t column
, row
;
1047 uint32_t index
, jump
;
1049 jump
= num
* gc_buffer_columns
;
1051 for ( row
= bottom
- 1 ; row
>= top
+ num
; row
-- )
1053 index
= row
* gc_buffer_columns
;
1055 for ( column
= 0 ; column
< gc_buffer_columns
; index
++, column
++ )
1057 if ( gc_buffer_attributes
[index
] != gc_buffer_attributes
[index
- jump
] ||
1058 gc_buffer_characters
[index
] != gc_buffer_characters
[index
- jump
] ||
1059 gc_buffer_colorcodes
[index
] != gc_buffer_colorcodes
[index
- jump
] )
1061 if ( gc_color_code
!= gc_buffer_colorcodes
[index
- jump
] )
1063 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes
[index
- jump
], TRUE
), TRUE
);
1064 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes
[index
- jump
], FALSE
), FALSE
);
1067 if ( gc_buffer_colorcodes
[index
] != gc_buffer_colorcodes
[index
- jump
] )
1069 gc_ops
.paint_char( /* xx */ column
,
1071 /* ch */ gc_buffer_characters
[index
- jump
],
1072 /* attrs */ gc_buffer_attributes
[index
- jump
],
1073 /* ch_previous */ 0,
1074 /* attrs_previous */ 0 );
1078 gc_ops
.paint_char( /* xx */ column
,
1080 /* ch */ gc_buffer_characters
[index
- jump
],
1081 /* attrs */ gc_buffer_attributes
[index
- jump
],
1082 /* ch_previous */ gc_buffer_characters
[index
],
1083 /* attrs_previous */ gc_buffer_attributes
[index
] );
1086 gc_buffer_attributes
[index
] = gc_buffer_attributes
[index
- jump
];
1087 gc_buffer_characters
[index
] = gc_buffer_characters
[index
- jump
];
1088 gc_buffer_colorcodes
[index
] = gc_buffer_colorcodes
[index
- jump
];
1093 if ( colorcodesave
!= gc_color_code
)
1095 gc_update_color(COLOR_CODE_GET(colorcodesave
, TRUE
), TRUE
);
1096 gc_update_color(COLOR_CODE_GET(colorcodesave
, FALSE
), FALSE
);
1099 /* Now set the freed up lines to the background colour */
1101 for ( row
= top
; row
< top
+ num
; row
++ )
1103 index
= row
* gc_buffer_columns
;
1105 for ( column
= 0 ; column
< gc_buffer_columns
; index
++, column
++ )
1107 if ( gc_buffer_attributes
[index
] != ATTR_NONE
||
1108 gc_buffer_characters
[index
] != ' ' ||
1109 gc_buffer_colorcodes
[index
] != gc_color_code
)
1111 if ( gc_buffer_colorcodes
[index
] != gc_color_code
)
1113 gc_ops
.paint_char( /* xx */ column
,
1116 /* attrs */ ATTR_NONE
,
1117 /* ch_previous */ 0,
1118 /* attrs_previous */ 0 );
1122 gc_ops
.paint_char( /* xx */ column
,
1125 /* attrs */ ATTR_NONE
,
1126 /* ch_previous */ gc_buffer_characters
[index
],
1127 /* attrs_previous */ gc_buffer_attributes
[index
] );
1130 gc_buffer_attributes
[index
] = ATTR_NONE
;
1131 gc_buffer_characters
[index
] = ' ';
1132 gc_buffer_colorcodes
[index
] = gc_color_code
;
1139 gc_ops
.scroll_down(num
, top
, bottom
);
1141 /* Now set the freed up lines to the background colour */
1143 gc_clear_screen(vinfo
.v_columns
- 1, top
+ num
- 1, top
, bottom
, 1);
1148 gc_scroll_up(int num
, unsigned int top
, unsigned int bottom
)
1150 if (!gc_buffer_size
) return;
1152 if ( bottom
<= gc_buffer_rows
)
1154 unsigned char colorcodesave
= gc_color_code
;
1155 uint32_t column
, row
;
1156 uint32_t index
, jump
;
1158 jump
= num
* gc_buffer_columns
;
1160 for ( row
= top
; row
< bottom
- num
; row
++ )
1162 index
= row
* gc_buffer_columns
;
1164 for ( column
= 0 ; column
< gc_buffer_columns
; index
++, column
++ )
1166 if ( gc_buffer_attributes
[index
] != gc_buffer_attributes
[index
+ jump
] ||
1167 gc_buffer_characters
[index
] != gc_buffer_characters
[index
+ jump
] ||
1168 gc_buffer_colorcodes
[index
] != gc_buffer_colorcodes
[index
+ jump
] )
1170 if ( gc_color_code
!= gc_buffer_colorcodes
[index
+ jump
] )
1172 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes
[index
+ jump
], TRUE
), TRUE
);
1173 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes
[index
+ jump
], FALSE
), FALSE
);
1176 if ( gc_buffer_colorcodes
[index
] != gc_buffer_colorcodes
[index
+ jump
] )
1178 gc_ops
.paint_char( /* xx */ column
,
1180 /* ch */ gc_buffer_characters
[index
+ jump
],
1181 /* attrs */ gc_buffer_attributes
[index
+ jump
],
1182 /* ch_previous */ 0,
1183 /* attrs_previous */ 0 );
1187 gc_ops
.paint_char( /* xx */ column
,
1189 /* ch */ gc_buffer_characters
[index
+ jump
],
1190 /* attrs */ gc_buffer_attributes
[index
+ jump
],
1191 /* ch_previous */ gc_buffer_characters
[index
],
1192 /* attrs_previous */ gc_buffer_attributes
[index
] );
1195 gc_buffer_attributes
[index
] = gc_buffer_attributes
[index
+ jump
];
1196 gc_buffer_characters
[index
] = gc_buffer_characters
[index
+ jump
];
1197 gc_buffer_colorcodes
[index
] = gc_buffer_colorcodes
[index
+ jump
];
1202 if ( colorcodesave
!= gc_color_code
)
1204 gc_update_color(COLOR_CODE_GET(colorcodesave
, TRUE
), TRUE
);
1205 gc_update_color(COLOR_CODE_GET(colorcodesave
, FALSE
), FALSE
);
1208 /* Now set the freed up lines to the background colour */
1210 for ( row
= bottom
- num
; row
< bottom
; row
++ )
1212 index
= row
* gc_buffer_columns
;
1214 for ( column
= 0 ; column
< gc_buffer_columns
; index
++, column
++ )
1216 if ( gc_buffer_attributes
[index
] != ATTR_NONE
||
1217 gc_buffer_characters
[index
] != ' ' ||
1218 gc_buffer_colorcodes
[index
] != gc_color_code
)
1220 if ( gc_buffer_colorcodes
[index
] != gc_color_code
)
1222 gc_ops
.paint_char( /* xx */ column
,
1225 /* attrs */ ATTR_NONE
,
1226 /* ch_previous */ 0,
1227 /* attrs_previous */ 0 );
1231 gc_ops
.paint_char( /* xx */ column
,
1234 /* attrs */ ATTR_NONE
,
1235 /* ch_previous */ gc_buffer_characters
[index
],
1236 /* attrs_previous */ gc_buffer_attributes
[index
] );
1239 gc_buffer_attributes
[index
] = ATTR_NONE
;
1240 gc_buffer_characters
[index
] = ' ';
1241 gc_buffer_colorcodes
[index
] = gc_color_code
;
1248 gc_ops
.scroll_up(num
, top
, bottom
);
1250 /* Now set the freed up lines to the background colour */
1252 gc_clear_screen(0, bottom
- num
, top
, bottom
, 0);
1257 gc_show_cursor(unsigned int xx
, unsigned int yy
)
1259 if ( xx
< gc_buffer_columns
&& yy
< gc_buffer_rows
)
1261 uint32_t index
= (yy
* gc_buffer_columns
) + xx
;
1262 unsigned char attribute
= gc_buffer_attributes
[index
];
1263 unsigned char character
= gc_buffer_characters
[index
];
1264 unsigned char colorcode
= gc_buffer_colorcodes
[index
];
1265 unsigned char colorcodesave
= gc_color_code
;
1267 gc_update_color(COLOR_CODE_GET(colorcode
, FALSE
), TRUE
);
1268 gc_update_color(COLOR_CODE_GET(colorcode
, TRUE
), FALSE
);
1270 gc_ops
.paint_char(xx
, yy
, character
, attribute
, 0, 0);
1272 gc_update_color(COLOR_CODE_GET(colorcodesave
, TRUE
), TRUE
);
1273 gc_update_color(COLOR_CODE_GET(colorcodesave
, FALSE
), FALSE
);
1277 gc_ops
.show_cursor(xx
, yy
);
1282 gc_update_color(int color
, boolean_t fore
)
1284 assert(gc_ops
.update_color
);
1286 gc_color_code
= COLOR_CODE_SET(gc_color_code
, color
, fore
);
1287 gc_ops
.update_color(color
, fore
);
1291 vcputc(__unused
int l
, __unused
int u
, int c
)
1293 if ( gc_initialized
&& ( gc_enabled
|| debug_mode
) )
1298 #if defined(__i386__) || defined(__x86_64__)
1299 x86_filter_TLB_coherency_interrupts(TRUE
);
1302 if ( gc_enabled
|| debug_mode
)
1304 gc_hide_cursor(gc_x
, gc_y
);
1306 gc_show_cursor(gc_x
, gc_y
);
1308 VCPUTC_LOCK_UNLOCK();
1309 #if defined(__i386__) || defined(__x86_64__)
1310 x86_filter_TLB_coherency_interrupts(FALSE
);
1317 * Video Console (Back-End)
1318 * ------------------------
1322 * For the color support (Michel Pollet)
1324 static unsigned char vc_color_index_table
[33] =
1325 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1326 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 2 };
1328 static uint32_t vc_colors
[8][4] = {
1329 { 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000 }, /* black */
1330 { 0x23232323, 0x7C007C00, 0x00FF0000, 0x3FF00000 }, /* red */
1331 { 0xb9b9b9b9, 0x03e003e0, 0x0000FF00, 0x000FFC00 }, /* green */
1332 { 0x05050505, 0x7FE07FE0, 0x00FFFF00, 0x3FFFFC00 }, /* yellow */
1333 { 0xd2d2d2d2, 0x001f001f, 0x000000FF, 0x000003FF }, /* blue */
1334 // { 0x80808080, 0x31933193, 0x00666699, 0x00000000 }, /* blue */
1335 { 0x18181818, 0x7C1F7C1F, 0x00FF00FF, 0x3FF003FF }, /* magenta */
1336 { 0xb4b4b4b4, 0x03FF03FF, 0x0000FFFF, 0x000FFFFF }, /* cyan */
1337 { 0x00000000, 0x7FFF7FFF, 0x00FFFFFF, 0x3FFFFFFF } /* white */
1340 static uint32_t vc_color_fore
= 0;
1341 static uint32_t vc_color_back
= 0;
1344 * New Rendering code from Michel Pollet
1347 /* Rendered Font Buffer */
1348 static unsigned char *vc_rendered_font
= NULL
;
1350 /* Rendered Font Size */
1351 static uint32_t vc_rendered_font_size
= 0;
1353 /* Size of a character in the table (bytes) */
1354 static int vc_rendered_char_size
= 0;
1356 #define REN_MAX_DEPTH 32
1357 static unsigned char vc_rendered_char
[ISO_CHAR_HEIGHT
* ((REN_MAX_DEPTH
/ 8) * ISO_CHAR_WIDTH
)];
1360 vc_clear_screen(unsigned int xx
, unsigned int yy
, unsigned int scrreg_top
,
1361 unsigned int scrreg_bottom
, int which
)
1363 uint32_t *p
, *endp
, *row
;
1365 int rowline
, rowlongs
;
1370 linelongs
= vinfo
.v_rowbytes
* (ISO_CHAR_HEIGHT
>> 2);
1371 rowline
= vinfo
.v_rowscanbytes
>> 2;
1372 rowlongs
= vinfo
.v_rowbytes
>> 2;
1374 p
= (uint32_t*) vinfo
.v_baseaddr
;
1375 endp
= (uint32_t*) vinfo
.v_baseaddr
;
1378 case 0: /* To end of screen */
1379 gc_clear_line(xx
, yy
, 0);
1380 if (yy
< scrreg_bottom
- 1) {
1381 p
+= (yy
+ 1) * linelongs
;
1382 endp
+= scrreg_bottom
* linelongs
;
1385 case 1: /* To start of screen */
1386 gc_clear_line(xx
, yy
, 1);
1387 if (yy
> scrreg_top
) {
1388 p
+= scrreg_top
* linelongs
;
1389 endp
+= yy
* linelongs
;
1392 case 2: /* Whole screen */
1393 p
+= scrreg_top
* linelongs
;
1394 if (scrreg_bottom
== vinfo
.v_rows
) {
1395 endp
+= rowlongs
* vinfo
.v_height
;
1397 endp
+= scrreg_bottom
* linelongs
;
1402 for (row
= p
; row
< endp
; row
+= rowlongs
) {
1403 for (col
= 0; col
< rowline
; col
++)
1404 *(row
+col
) = vc_color_back
;
1409 vc_render_char(unsigned char ch
, unsigned char *renderptr
, short newdepth
)
1412 unsigned char *charptr
;
1413 unsigned short *shortptr
;
1415 } current
; /* current place in rendered font, multiple types. */
1416 unsigned char *theChar
; /* current char in iso_font */
1419 current
.charptr
= renderptr
;
1420 theChar
= iso_font
+ (ch
* ISO_CHAR_HEIGHT
);
1422 for (line
= 0; line
< ISO_CHAR_HEIGHT
; line
++) {
1423 unsigned char mask
= 1;
1427 *current
.charptr
++ = (*theChar
& mask
) ? 0xFF : 0;
1430 *current
.shortptr
++ = (*theChar
& mask
) ? 0xFFFF : 0;
1435 *current
.longptr
++ = (*theChar
& mask
) ? 0xFFFFFFFF : 0;
1439 } while (mask
); /* while the single bit drops to the right */
1445 vc_paint_char_8(unsigned int xx
, unsigned int yy
, unsigned char ch
, int attrs
,
1446 __unused
unsigned char ch_previous
, __unused
int attrs_previous
)
1452 if (vc_rendered_font
) {
1453 theChar
= (uint32_t*)(vc_rendered_font
+ (ch
* vc_rendered_char_size
));
1455 vc_render_char(ch
, vc_rendered_char
, 8);
1456 theChar
= (uint32_t*)(vc_rendered_char
);
1458 where
= (uint32_t*)(vinfo
.v_baseaddr
+
1459 (yy
* ISO_CHAR_HEIGHT
* vinfo
.v_rowbytes
) +
1460 (xx
* ISO_CHAR_WIDTH
));
1462 if (!attrs
) for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* No attr? FLY !*/
1463 uint32_t *store
= where
;
1465 for (x
= 0; x
< 2; x
++) {
1466 uint32_t val
= *theChar
++;
1467 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1471 where
= (uint32_t*)(((unsigned char*)where
)+vinfo
.v_rowbytes
);
1472 } else for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* a little slower */
1473 uint32_t *store
= where
, lastpixel
= 0;
1475 for (x
= 0 ; x
< 2; x
++) {
1476 uint32_t val
= *theChar
++, save
= val
;
1477 if (attrs
& ATTR_BOLD
) { /* bold support */
1478 if (lastpixel
&& !(save
& 0xFF000000))
1480 if ((save
& 0xFFFF0000) == 0xFF000000)
1482 if ((save
& 0x00FFFF00) == 0x00FF0000)
1484 if ((save
& 0x0000FFFF) == 0x0000FF00)
1487 if (attrs
& ATTR_REVERSE
) val
= ~val
;
1488 if (attrs
& ATTR_UNDER
&& i
== ISO_CHAR_HEIGHT
-1) val
= ~val
;
1490 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1492 lastpixel
= save
& 0xff;
1495 where
= (uint32_t*)(((unsigned char*)where
)+vinfo
.v_rowbytes
);
1501 vc_paint_char_16(unsigned int xx
, unsigned int yy
, unsigned char ch
, int attrs
,
1502 __unused
unsigned char ch_previous
,
1503 __unused
int attrs_previous
)
1509 if (vc_rendered_font
) {
1510 theChar
= (uint32_t*)(vc_rendered_font
+ (ch
* vc_rendered_char_size
));
1512 vc_render_char(ch
, vc_rendered_char
, 16);
1513 theChar
= (uint32_t*)(vc_rendered_char
);
1515 where
= (uint32_t*)(vinfo
.v_baseaddr
+
1516 (yy
* ISO_CHAR_HEIGHT
* vinfo
.v_rowbytes
) +
1517 (xx
* ISO_CHAR_WIDTH
* 2));
1519 if (!attrs
) for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* No attrs ? FLY ! */
1520 uint32_t *store
= where
;
1522 for (x
= 0; x
< 4; x
++) {
1523 uint32_t val
= *theChar
++;
1524 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1528 where
= (uint32_t*)(((unsigned char*)where
)+vinfo
.v_rowbytes
);
1529 } else for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* a little bit slower */
1530 uint32_t *store
= where
, lastpixel
= 0;
1532 for (x
= 0 ; x
< 4; x
++) {
1533 uint32_t val
= *theChar
++, save
= val
;
1534 if (attrs
& ATTR_BOLD
) { /* bold support */
1535 if (save
== 0xFFFF0000) val
|= 0xFFFF;
1536 else if (lastpixel
&& !(save
& 0xFFFF0000))
1539 if (attrs
& ATTR_REVERSE
) val
= ~val
;
1540 if (attrs
& ATTR_UNDER
&& i
== ISO_CHAR_HEIGHT
-1) val
= ~val
;
1542 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1545 lastpixel
= save
& 0x7fff;
1548 where
= (uint32_t*)(((unsigned char*)where
)+vinfo
.v_rowbytes
);
1554 vc_paint_char_32(unsigned int xx
, unsigned int yy
, unsigned char ch
, int attrs
,
1555 unsigned char ch_previous
, int attrs_previous
)
1558 uint32_t *theCharPrevious
;
1562 if (vc_rendered_font
) {
1563 theChar
= (uint32_t*)(vc_rendered_font
+ (ch
* vc_rendered_char_size
));
1564 theCharPrevious
= (uint32_t*)(vc_rendered_font
+ (ch_previous
* vc_rendered_char_size
));
1566 vc_render_char(ch
, vc_rendered_char
, 32);
1567 theChar
= (uint32_t*)(vc_rendered_char
);
1568 theCharPrevious
= NULL
;
1571 theCharPrevious
= NULL
;
1573 if (attrs_previous
) {
1574 theCharPrevious
= NULL
;
1576 where
= (uint32_t*)(vinfo
.v_baseaddr
+
1577 (yy
* ISO_CHAR_HEIGHT
* vinfo
.v_rowbytes
) +
1578 (xx
* ISO_CHAR_WIDTH
* 4));
1580 if (!attrs
) for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* No attrs ? FLY ! */
1581 uint32_t *store
= where
;
1583 for (x
= 0; x
< 8; x
++) {
1584 uint32_t val
= *theChar
++;
1585 if (theCharPrevious
== NULL
|| val
!= *theCharPrevious
++ ) {
1586 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1593 where
= (uint32_t *)(((unsigned char*)where
)+vinfo
.v_rowbytes
);
1594 } else for (i
= 0; i
< ISO_CHAR_HEIGHT
; i
++) { /* a little slower */
1595 uint32_t *store
= where
, lastpixel
= 0;
1597 for (x
= 0 ; x
< 8; x
++) {
1598 uint32_t val
= *theChar
++, save
= val
;
1599 if (attrs
& ATTR_BOLD
) { /* bold support */
1600 if (lastpixel
&& !save
)
1603 if (attrs
& ATTR_REVERSE
) val
= ~val
;
1604 if (attrs
& ATTR_UNDER
&& i
== ISO_CHAR_HEIGHT
-1) val
= ~val
;
1606 val
= (vc_color_back
& ~val
) | (vc_color_fore
& val
);
1611 where
= (uint32_t*)(((unsigned char*)where
)+vinfo
.v_rowbytes
);
1617 vc_paint_char(unsigned int xx
, unsigned int yy
, unsigned char ch
, int attrs
,
1618 unsigned char ch_previous
, int attrs_previous
)
1623 switch(vinfo
.v_depth
) {
1625 vc_paint_char_8(xx
, yy
, ch
, attrs
, ch_previous
, attrs_previous
);
1628 vc_paint_char_16(xx
, yy
, ch
, attrs
, ch_previous
,
1633 vc_paint_char_32(xx
, yy
, ch
, attrs
, ch_previous
,
1640 vc_render_font(short newdepth
)
1642 static short olddepth
= 0;
1644 int charindex
; /* index in ISO font */
1645 unsigned char *rendered_font
;
1646 unsigned int rendered_font_size
;
1647 int rendered_char_size
;
1650 if (vm_initialized
== FALSE
) {
1651 return; /* nothing to do */
1653 if (olddepth
== newdepth
&& vc_rendered_font
) {
1654 return; /* nothing to do */
1660 rendered_font
= vc_rendered_font
;
1661 rendered_font_size
= vc_rendered_font_size
;
1662 rendered_char_size
= vc_rendered_char_size
;
1664 vc_rendered_font
= NULL
;
1665 vc_rendered_font_size
= 0;
1666 vc_rendered_char_size
= 0;
1668 VCPUTC_LOCK_UNLOCK();
1671 if (rendered_font
) {
1672 kfree(rendered_font
, rendered_font_size
);
1673 rendered_font
= NULL
;
1677 rendered_char_size
= ISO_CHAR_HEIGHT
* (((newdepth
+ 7) / 8) * ISO_CHAR_WIDTH
);
1678 rendered_font_size
= (ISO_CHAR_MAX
-ISO_CHAR_MIN
+1) * rendered_char_size
;
1679 rendered_font
= (unsigned char *) kalloc(rendered_font_size
);
1682 if (rendered_font
== NULL
) {
1686 for (charindex
= ISO_CHAR_MIN
; charindex
<= ISO_CHAR_MAX
; charindex
++) {
1687 vc_render_char(charindex
, rendered_font
+ (charindex
* rendered_char_size
), newdepth
);
1690 olddepth
= newdepth
;
1695 vc_rendered_font
= rendered_font
;
1696 vc_rendered_font_size
= rendered_font_size
;
1697 vc_rendered_char_size
= rendered_char_size
;
1699 VCPUTC_LOCK_UNLOCK();
1704 vc_enable(boolean_t enable
)
1706 vc_render_font(enable
? vinfo
.v_depth
: 0);
1710 vc_reverse_cursor(unsigned int xx
, unsigned int yy
)
1718 where
= (uint32_t*)(vinfo
.v_baseaddr
+
1719 (yy
* ISO_CHAR_HEIGHT
* vinfo
.v_rowbytes
) +
1720 (xx
/** ISO_CHAR_WIDTH*/ * vinfo
.v_depth
));
1721 for (line
= 0; line
< ISO_CHAR_HEIGHT
; line
++) {
1722 switch (vinfo
.v_depth
) {
1724 where
[0] = ~where
[0];
1725 where
[1] = ~where
[1];
1728 for (col
= 0; col
< 4; col
++)
1729 where
[col
] = ~where
[col
];
1732 for (col
= 0; col
< 8; col
++)
1733 where
[col
] = ~where
[col
];
1736 where
= (uint32_t*)(((unsigned char*)where
)+vinfo
.v_rowbytes
);
1741 vc_scroll_down(int num
, unsigned int scrreg_top
, unsigned int scrreg_bottom
)
1743 uint32_t *from
, *to
, linelongs
, i
, line
, rowline
, rowscanline
;
1748 linelongs
= vinfo
.v_rowbytes
* (ISO_CHAR_HEIGHT
>> 2);
1749 rowline
= vinfo
.v_rowbytes
>> 2;
1750 rowscanline
= vinfo
.v_rowscanbytes
>> 2;
1752 to
= (uint32_t *) vinfo
.v_baseaddr
+ (linelongs
* scrreg_bottom
)
1753 - (rowline
- rowscanline
);
1754 from
= to
- (linelongs
* num
); /* handle multiple line scroll (Michel Pollet) */
1756 i
= (scrreg_bottom
- scrreg_top
) - num
;
1759 for (line
= 0; line
< ISO_CHAR_HEIGHT
; line
++) {
1761 * Only copy what is displayed
1763 video_scroll_down(from
,
1764 (from
-(vinfo
.v_rowscanbytes
>> 2)),
1774 vc_scroll_up(int num
, unsigned int scrreg_top
, unsigned int scrreg_bottom
)
1776 uint32_t *from
, *to
, linelongs
, i
, line
, rowline
, rowscanline
;
1781 linelongs
= vinfo
.v_rowbytes
* (ISO_CHAR_HEIGHT
>> 2);
1782 rowline
= vinfo
.v_rowbytes
>> 2;
1783 rowscanline
= vinfo
.v_rowscanbytes
>> 2;
1785 to
= (uint32_t *) vinfo
.v_baseaddr
+ (scrreg_top
* linelongs
);
1786 from
= to
+ (linelongs
* num
); /* handle multiple line scroll (Michel Pollet) */
1788 i
= (scrreg_bottom
- scrreg_top
) - num
;
1791 for (line
= 0; line
< ISO_CHAR_HEIGHT
; line
++) {
1793 * Only copy what is displayed
1795 video_scroll_up(from
,
1796 (from
+(vinfo
.v_rowscanbytes
>> 2)),
1806 vc_update_color(int color
, boolean_t fore
)
1811 vc_color_fore
= vc_colors
[color
][vc_color_index_table
[vinfo
.v_depth
]];
1813 vc_color_back
= vc_colors
[color
][vc_color_index_table
[vinfo
.v_depth
]];
1818 * Video Console (Back-End): Icon Control
1819 * --------------------------------------
1822 static vc_progress_element
* vc_progress
;
1823 static const unsigned char * vc_progress_data
[2];
1824 static const unsigned char * vc_progress_alpha
;
1825 static boolean_t vc_progress_enable
;
1826 static const unsigned char * vc_clut
;
1827 static const unsigned char * vc_clut8
;
1828 static unsigned char vc_revclut8
[256];
1829 static uint32_t vc_progress_interval
;
1830 static uint32_t vc_progress_count
;
1831 static uint32_t vc_progress_angle
;
1832 static uint64_t vc_progress_deadline
;
1833 static thread_call_data_t vc_progress_call
;
1834 static boolean_t vc_needsave
;
1835 static void * vc_saveunder
;
1836 static vm_size_t vc_saveunder_len
;
1837 static int8_t vc_uiselect
= 0;
1838 decl_simple_lock_data(,vc_progress_lock
)
1842 kDataIndexed
= 0x20,
1852 static void vc_blit_rect(int x
, int y
, int bx
,
1853 int width
, int height
,
1854 int sourceRow
, int backRow
,
1855 const unsigned char * dataPtr
,
1857 unsigned int flags
);
1858 static void vc_blit_rect_8(int x
, int y
, int bx
,
1859 int width
, int height
,
1860 int sourceRow
, int backRow
,
1861 const unsigned char * dataPtr
,
1862 unsigned char * backBuffer
,
1863 unsigned int flags
);
1864 static void vc_blit_rect_16(int x
, int y
, int bx
,
1865 int width
, int height
,
1866 int sourceRow
, int backRow
,
1867 const unsigned char * dataPtr
,
1868 unsigned short * backBuffer
,
1869 unsigned int flags
);
1870 static void vc_blit_rect_32(int x
, int y
, int bx
,
1871 int width
, int height
,
1872 int sourceRow
, int backRow
,
1873 const unsigned char * dataPtr
,
1874 unsigned int * backBuffer
,
1875 unsigned int flags
);
1876 static void vc_blit_rect_30(int x
, int y
, int bx
,
1877 int width
, int height
,
1878 int sourceRow
, int backRow
,
1879 const unsigned char * dataPtr
,
1880 unsigned int * backBuffer
,
1881 unsigned int flags
);
1882 static void vc_progress_task( void * arg0
, void * arg
);
1884 static void vc_blit_rect(int x
, int y
, int bx
,
1885 int width
, int height
,
1886 int sourceRow
, int backRow
,
1887 const unsigned char * dataPtr
,
1894 switch( vinfo
.v_depth
) {
1896 if( vc_clut8
== vc_clut
)
1897 vc_blit_rect_8( x
, y
, bx
, width
, height
, sourceRow
, backRow
, dataPtr
, (unsigned char *) backBuffer
, flags
);
1900 vc_blit_rect_16( x
, y
, bx
, width
, height
, sourceRow
, backRow
, dataPtr
, (unsigned short *) backBuffer
, flags
);
1903 vc_blit_rect_32( x
, y
, bx
, width
, height
, sourceRow
, backRow
, dataPtr
, (unsigned int *) backBuffer
, flags
);
1906 vc_blit_rect_30( x
, y
, bx
, width
, height
, sourceRow
, backRow
, dataPtr
, (unsigned int *) backBuffer
, flags
);
1912 vc_blit_rect_8(int x
, int y
, __unused
int bx
,
1913 int width
, int height
,
1914 int sourceRow
, __unused
int backRow
,
1915 const unsigned char * dataPtr
,
1916 __unused
unsigned char * backBuffer
,
1917 __unused
unsigned int flags
)
1919 volatile unsigned short * dst
;
1921 unsigned int data
= 0, out
= 0;
1922 int sx
, sy
, a
, b
, c
, d
;
1923 int scale
= 0x10000;
1925 a
= vc_rotate_matr
[kDataRotate
& flags
][0][0] * scale
;
1926 b
= vc_rotate_matr
[kDataRotate
& flags
][0][1] * scale
;
1927 c
= vc_rotate_matr
[kDataRotate
& flags
][1][0] * scale
;
1928 d
= vc_rotate_matr
[kDataRotate
& flags
][1][1] * scale
;
1929 sx
= ((a
+ b
) < 0) ? ((width
* scale
) - 0x8000) : 0;
1930 sy
= ((c
+ d
) < 0) ? ((height
* scale
) - 0x8000) : 0;
1932 if (!sourceRow
) data
= (unsigned int)(uintptr_t)dataPtr
;
1933 else if (1 == sourceRow
) a
= 0;
1935 dst
= (volatile unsigned short *) (vinfo
.v_baseaddr
+
1936 (y
* vinfo
.v_rowbytes
) +
1939 for( line
= 0; line
< height
; line
++)
1941 for( col
= 0; col
< width
; col
++)
1943 if (sourceRow
) data
= dataPtr
[((sx
+ (col
* a
) + (line
* b
)) >> 16)
1944 + sourceRow
* (((sy
+ (col
* c
) + (line
* d
)) >> 16))];
1945 if (kDataAlpha
& flags
)
1946 out
= vc_revclut8
[data
];
1951 dst
= (volatile unsigned short *) (((volatile char*)dst
) + vinfo
.v_rowbytes
);
1955 /* For ARM, 16-bit is 565 (RGB); it is 1555 (XRGB) on other platforms */
1957 #define CLUT_MASK_R 0xf8
1958 #define CLUT_MASK_G 0xf8
1959 #define CLUT_MASK_B 0xf8
1960 #define CLUT_SHIFT_R << 7
1961 #define CLUT_SHIFT_G << 2
1962 #define CLUT_SHIFT_B >> 3
1963 #define MASK_R 0x7c00
1964 #define MASK_G 0x03e0
1965 #define MASK_B 0x001f
1966 #define MASK_R_8 0x3fc00
1967 #define MASK_G_8 0x01fe0
1968 #define MASK_B_8 0x000ff
1970 static void vc_blit_rect_16( int x
, int y
, int bx
,
1971 int width
, int height
,
1972 int sourceRow
, int backRow
,
1973 const unsigned char * dataPtr
,
1974 unsigned short * backPtr
,
1977 volatile unsigned short * dst
;
1979 unsigned int data
= 0, out
= 0, back
= 0;
1980 int sx
, sy
, a
, b
, c
, d
;
1981 int scale
= 0x10000;
1983 a
= vc_rotate_matr
[kDataRotate
& flags
][0][0] * scale
;
1984 b
= vc_rotate_matr
[kDataRotate
& flags
][0][1] * scale
;
1985 c
= vc_rotate_matr
[kDataRotate
& flags
][1][0] * scale
;
1986 d
= vc_rotate_matr
[kDataRotate
& flags
][1][1] * scale
;
1987 sx
= ((a
+ b
) < 0) ? ((width
* scale
) - 0x8000) : 0;
1988 sy
= ((c
+ d
) < 0) ? ((height
* scale
) - 0x8000) : 0;
1990 if (!sourceRow
) data
= (unsigned int)(uintptr_t)dataPtr
;
1991 else if (1 == sourceRow
) a
= 0;
1995 dst
= (volatile unsigned short *) (vinfo
.v_baseaddr
+
1996 (y
* vinfo
.v_rowbytes
) +
1999 for( line
= 0; line
< height
; line
++)
2001 for( col
= 0; col
< width
; col
++)
2003 if (sourceRow
) data
= dataPtr
[((sx
+ (col
* a
) + (line
* b
)) >> 16)
2004 + sourceRow
* (((sy
+ (col
* c
) + (line
* d
)) >> 16))];
2006 if (kSave
& flags
) {
2007 back
= *(dst
+ col
);
2012 if (kDataIndexed
& flags
) {
2013 out
= ( (CLUT_MASK_R
& (vc_clut
[data
*3 + 0])) CLUT_SHIFT_R
)
2014 | ( (CLUT_MASK_G
& (vc_clut
[data
*3 + 1])) CLUT_SHIFT_G
)
2015 | ( (CLUT_MASK_B
& (vc_clut
[data
*3 + 2])) CLUT_SHIFT_B
);
2016 } else if (kDataAlpha
& flags
) {
2017 out
= (((((back
& MASK_R
) * data
) + MASK_R_8
) >> 8) & MASK_R
)
2018 | (((((back
& MASK_G
) * data
) + MASK_G_8
) >> 8) & MASK_G
)
2019 | (((((back
& MASK_B
) * data
) + MASK_B_8
) >> 8) & MASK_B
);
2020 #ifdef CONFIG_VC_PROGRESS_WHITE
2021 out
+= (((0xff - data
) & CLUT_MASK_R
) CLUT_SHIFT_R
)
2022 | (((0xff - data
) & CLUT_MASK_G
) CLUT_SHIFT_G
)
2023 | (((0xff - data
) & CLUT_MASK_B
) CLUT_SHIFT_B
);
2029 dst
= (volatile unsigned short *) (((volatile char*)dst
) + vinfo
.v_rowbytes
);
2031 backPtr
+= backRow
- width
;
2036 static void vc_blit_rect_32(int x
, int y
, int bx
,
2037 int width
, int height
,
2038 int sourceRow
, int backRow
,
2039 const unsigned char * dataPtr
,
2040 unsigned int * backPtr
,
2043 volatile unsigned int * dst
;
2045 unsigned int data
= 0, out
= 0, back
= 0;
2046 int sx
, sy
, a
, b
, c
, d
;
2047 int scale
= 0x10000;
2049 a
= vc_rotate_matr
[kDataRotate
& flags
][0][0] * scale
;
2050 b
= vc_rotate_matr
[kDataRotate
& flags
][0][1] * scale
;
2051 c
= vc_rotate_matr
[kDataRotate
& flags
][1][0] * scale
;
2052 d
= vc_rotate_matr
[kDataRotate
& flags
][1][1] * scale
;
2053 sx
= ((a
+ b
) < 0) ? ((width
* scale
) - 0x8000) : 0;
2054 sy
= ((c
+ d
) < 0) ? ((height
* scale
) - 0x8000) : 0;
2056 if (!sourceRow
) data
= (unsigned int)(uintptr_t)dataPtr
;
2057 else if (1 == sourceRow
) a
= 0;
2061 dst
= (volatile unsigned int *) (vinfo
.v_baseaddr
+
2062 (y
* vinfo
.v_rowbytes
) +
2065 for( line
= 0; line
< height
; line
++)
2067 for( col
= 0; col
< width
; col
++)
2069 if (sourceRow
) data
= dataPtr
[((sx
+ (col
* a
) + (line
* b
)) >> 16)
2070 + sourceRow
* (((sy
+ (col
* c
) + (line
* d
)) >> 16))];
2072 if (kSave
& flags
) {
2073 back
= *(dst
+ col
);
2078 if (kDataIndexed
& flags
) {
2079 out
= (vc_clut
[data
*3 + 0] << 16)
2080 | (vc_clut
[data
*3 + 1] << 8)
2081 | (vc_clut
[data
*3 + 2]);
2082 } else if (kDataAlpha
& flags
) {
2083 out
= (((((back
& 0x00ff00ff) * data
) + 0x00ff00ff) >> 8) & 0x00ff00ff)
2084 | (((((back
& 0x0000ff00) * data
) + 0x0000ff00) >> 8) & 0x0000ff00);
2085 #ifdef CONFIG_VC_PROGRESS_WHITE
2086 out
+= ((0xff - data
) << 16)
2087 | ((0xff - data
) << 8)
2094 dst
= (volatile unsigned int *) (((volatile char*)dst
) + vinfo
.v_rowbytes
);
2096 backPtr
+= backRow
- width
;
2100 static void vc_blit_rect_30(int x
, int y
, int bx
,
2101 int width
, int height
,
2102 int sourceRow
, int backRow
,
2103 const unsigned char * dataPtr
,
2104 unsigned int * backPtr
,
2107 volatile unsigned int * dst
;
2109 unsigned int data
= 0, out
= 0, back
= 0;
2110 unsigned long long exp
;
2111 int sx
, sy
, a
, b
, c
, d
;
2112 int scale
= 0x10000;
2114 a
= vc_rotate_matr
[kDataRotate
& flags
][0][0] * scale
;
2115 b
= vc_rotate_matr
[kDataRotate
& flags
][0][1] * scale
;
2116 c
= vc_rotate_matr
[kDataRotate
& flags
][1][0] * scale
;
2117 d
= vc_rotate_matr
[kDataRotate
& flags
][1][1] * scale
;
2118 sx
= ((a
+ b
) < 0) ? ((width
* scale
) - 0x8000) : 0;
2119 sy
= ((c
+ d
) < 0) ? ((height
* scale
) - 0x8000) : 0;
2121 if (!sourceRow
) data
= (unsigned int)(uintptr_t)dataPtr
;
2122 else if (1 == sourceRow
) a
= 0;
2126 dst
= (volatile unsigned int *) (vinfo
.v_baseaddr
+
2127 (y
* vinfo
.v_rowbytes
) +
2130 for( line
= 0; line
< height
; line
++)
2132 for( col
= 0; col
< width
; col
++)
2134 if (col
< sourceRow
)
2138 if (kSave
& flags
) {
2139 back
= *(dst
+ col
);
2144 if (kDataIndexed
& flags
) {
2145 out
= (vc_clut
[data
*3 + 0] << 22)
2146 | (vc_clut
[data
*3 + 1] << 12)
2147 | (vc_clut
[data
*3 + 2] << 2);
2148 } else if (kDataAlpha
& flags
) {
2150 exp
= (((((exp
& 0x3FF003FF) * data
) + 0x0FF000FF) >> 8) & 0x3FF003FF)
2151 | (((((exp
& 0x000FFC00) * data
) + 0x0003FC00) >> 8) & 0x000FFC00);
2152 out
= (unsigned int)exp
;
2153 #ifdef CONFIG_VC_PROGRESS_WHITE
2154 out
+= ((0xFF - data
) << 22)
2155 | ((0xFF - data
) << 12)
2156 | ((0xFF - data
) << 2);
2162 dst
= (volatile unsigned int *) (((volatile char*)dst
) + vinfo
.v_rowbytes
);
2164 backPtr
+= backRow
- width
;
2170 * Routines to render the lzss image format
2173 struct lzss_image_state
{
2178 uint32_t bytes_per_row
;
2179 volatile uint32_t * row_start
;
2180 const uint8_t* clut
;
2182 typedef struct lzss_image_state lzss_image_state
;
2184 // returns 0 if OK, 1 if error
2186 vc_decompress_lzss_next_pixel (int next_data
, lzss_image_state
* state
)
2188 uint32_t palette_index
= 0;
2189 uint32_t pixel_value
= 0;
2191 palette_index
= next_data
* 3;
2193 pixel_value
= ( (uint32_t) state
->clut
[palette_index
+ 0] << 16)
2194 | ( (uint32_t) state
->clut
[palette_index
+ 1] << 8)
2195 | ( (uint32_t) state
->clut
[palette_index
+ 2]);
2197 *(state
->row_start
+ state
->col
) = pixel_value
;
2199 if (++state
->col
>= state
->width
) {
2201 if (++state
->row
>= state
->height
) {
2204 state
->row_start
= (volatile uint32_t *) (((uintptr_t)state
->row_start
) + state
->bytes_per_row
);
2211 * Blit an lzss compressed image to the framebuffer
2212 * Assumes 32 bit screen (which is everything we ship at the moment)
2213 * The function vc_display_lzss_icon was copied from libkern/mkext.c, then modified.
2217 * TODO: Does lzss use too much stack? 4096 plus bytes...
2218 * Can probably chop it down by 1/2.
2221 /**************************************************************
2222 LZSS.C -- A Data Compression Program
2223 ***************************************************************
2224 4/6/1989 Haruhiko Okumura
2225 Use, distribute, and modify this program freely.
2226 Please send me your improved versions.
2228 NIFTY-Serve PAF01022
2229 CompuServe 74050,1022
2231 **************************************************************/
2233 #define N 4096 /* size of ring buffer - must be power of 2 */
2234 #define F 18 /* upper limit for match_length */
2235 #define THRESHOLD 2 /* encode string into position and length
2236 if match_length is greater than this */
2238 // returns 0 if OK, 1 if error
2239 // x and y indicate upper left corner of image location on screen
2241 vc_display_lzss_icon(uint32_t dst_x
, uint32_t dst_y
,
2242 uint32_t image_width
, uint32_t image_height
,
2243 const uint8_t *compressed_image
,
2244 uint32_t compressed_size
,
2245 const uint8_t *clut
)
2247 uint32_t* image_start
;
2248 uint32_t bytes_per_pixel
= 4;
2249 uint32_t bytes_per_row
= vinfo
.v_rowbytes
;
2251 image_start
= (uint32_t *) (vinfo
.v_baseaddr
+ (dst_y
* bytes_per_row
) + (dst_x
* bytes_per_pixel
));
2253 lzss_image_state state
= {0, 0, image_width
, image_height
, bytes_per_row
, image_start
, clut
};
2257 const uint8_t *src
= compressed_image
;
2258 uint32_t srclen
= compressed_size
;
2260 /* ring buffer of size N, with extra F-1 bytes to aid string comparison */
2261 uint8_t text_buf
[N
+ F
- 1];
2262 const uint8_t *srcend
= src
+ srclen
;
2266 srcend
= src
+ srclen
;
2267 for (i
= 0; i
< N
- F
; i
++)
2272 if (((flags
>>= 1) & 0x100) == 0) {
2273 if (src
< srcend
) c
= *src
++; else break;
2274 flags
= c
| 0xFF00; /* uses higher byte cleverly */
2275 } /* to count eight */
2277 if (src
< srcend
) c
= *src
++; else break;
2278 rval
= vc_decompress_lzss_next_pixel(c
, &state
);
2284 if (src
< srcend
) i
= *src
++; else break;
2285 if (src
< srcend
) j
= *src
++; else break;
2286 i
|= ((j
& 0xF0) << 4);
2287 j
= (j
& 0x0F) + THRESHOLD
;
2288 for (k
= 0; k
<= j
; k
++) {
2289 c
= text_buf
[(i
+ k
) & (N
- 1)];
2290 rval
= vc_decompress_lzss_next_pixel(c
, &state
);
2301 void noroot_icon_test(void) {
2302 boolean_t o_vc_progress_enable
= vc_progress_enable
;
2304 vc_progress_enable
= 1;
2306 PE_display_icon( 0, "noroot");
2308 vc_progress_enable
= o_vc_progress_enable
;
2312 void vc_display_icon( vc_progress_element
* desc
,
2313 const unsigned char * data
)
2315 int x
, y
, width
, height
;
2317 if( vc_progress_enable
&& vc_clut
) {
2319 width
= desc
->width
;
2320 height
= desc
->height
;
2323 if( 1 & desc
->flags
) {
2324 x
+= ((vinfo
.v_width
- width
) / 2);
2325 y
+= ((vinfo
.v_height
- height
) / 2);
2327 vc_blit_rect( x
, y
, 0, width
, height
, width
, 0, data
, NULL
, kDataIndexed
);
2332 vc_progress_initialize( vc_progress_element
* desc
,
2333 const unsigned char * data1x
,
2334 const unsigned char * data2x
,
2335 const unsigned char * clut
)
2339 if( (!clut
) || (!desc
) || (!data1x
))
2344 simple_lock_init(&vc_progress_lock
, 0);
2347 vc_progress_data
[0] = data1x
;
2348 vc_progress_data
[1] = data2x
;
2349 if( 2 & vc_progress
->flags
)
2350 vc_progress_alpha
= data1x
2351 + vc_progress
->count
* vc_progress
->width
* vc_progress
->height
;
2353 vc_progress_alpha
= NULL
;
2355 thread_call_setup(&vc_progress_call
, vc_progress_task
, NULL
);
2357 clock_interval_to_absolutetime_interval(vc_progress
->time
, 1000 * 1000, &abstime
);
2358 vc_progress_interval
= (uint32_t)abstime
;
2362 vc_progress_set(boolean_t enable
, uint32_t vc_delay
)
2365 void *saveBuf
= NULL
;
2366 vm_size_t saveLen
= 0;
2369 unsigned char pdata8
;
2370 unsigned short pdata16
;
2371 unsigned short * buf16
;
2372 unsigned int pdata32
;
2373 unsigned int * buf32
;
2379 saveLen
= (vc_progress
->width
<< vc_uiselect
) * (vc_progress
->height
<< vc_uiselect
) * vinfo
.v_depth
/ 8;
2380 saveBuf
= kalloc( saveLen
);
2382 switch( vinfo
.v_depth
) {
2384 for( count
= 0; count
< 256; count
++) {
2385 vc_revclut8
[count
] = vc_clut
[0x01 * 3];
2386 pdata8
= (vc_clut
[0x01 * 3] * count
+ 0x0ff) >> 8;
2387 for( index
= 0; index
< 256; index
++) {
2388 if( (pdata8
== vc_clut
[index
* 3 + 0]) &&
2389 (pdata8
== vc_clut
[index
* 3 + 1]) &&
2390 (pdata8
== vc_clut
[index
* 3 + 2])) {
2391 vc_revclut8
[count
] = index
;
2396 memset( saveBuf
, 0x01, saveLen
);
2400 buf16
= (unsigned short *) saveBuf
;
2401 pdata16
= ((vc_clut
[0x01 * 3 + 0] & CLUT_MASK_R
) CLUT_SHIFT_R
)
2402 | ((vc_clut
[0x01 * 3 + 0] & CLUT_MASK_G
) CLUT_SHIFT_G
)
2403 | ((vc_clut
[0x01 * 3 + 0] & CLUT_MASK_B
) CLUT_SHIFT_B
);
2404 for( count
= 0; count
< saveLen
/ 2; count
++)
2405 buf16
[count
] = pdata16
;
2409 buf32
= (unsigned int *) saveBuf
;
2410 pdata32
= ((vc_clut
[0x01 * 3 + 0] & 0xff) << 16)
2411 | ((vc_clut
[0x01 * 3 + 1] & 0xff) << 8)
2412 | ((vc_clut
[0x01 * 3 + 2] & 0xff) << 0);
2413 for( count
= 0; count
< saveLen
/ 4; count
++)
2414 buf32
[count
] = pdata32
;
2420 simple_lock(&vc_progress_lock
);
2422 if( vc_progress_enable
!= enable
) {
2423 vc_progress_enable
= enable
;
2426 vc_saveunder
= saveBuf
;
2427 vc_saveunder_len
= saveLen
;
2430 vc_progress_count
= 0;
2431 vc_progress_angle
= 0;
2433 clock_interval_to_deadline(vc_delay
,
2434 1000 * 1000 * 1000 /*second scale*/,
2435 &vc_progress_deadline
);
2436 thread_call_enter_delayed(&vc_progress_call
, vc_progress_deadline
);
2440 saveBuf
= vc_saveunder
;
2441 saveLen
= vc_saveunder_len
;
2442 vc_saveunder
= NULL
;
2443 vc_saveunder_len
= 0;
2446 thread_call_cancel(&vc_progress_call
);
2450 simple_unlock(&vc_progress_lock
);
2454 kfree( saveBuf
, saveLen
);
2459 vc_progress_task(__unused
void *arg0
, __unused
void *arg
)
2462 int x
, y
, width
, height
;
2463 const unsigned char * data
;
2466 simple_lock(&vc_progress_lock
);
2468 if( vc_progress_enable
) {
2470 vc_progress_count
++;
2471 if( vc_progress_count
>= vc_progress
->count
) {
2472 vc_progress_count
= 0;
2473 vc_progress_angle
++;
2476 width
= (vc_progress
->width
<< vc_uiselect
);
2477 height
= (vc_progress
->height
<< vc_uiselect
);
2478 x
= (vc_progress
->dx
<< vc_uiselect
);
2479 y
= (vc_progress
->dy
<< vc_uiselect
);
2480 data
= vc_progress_data
[vc_uiselect
];
2481 data
+= vc_progress_count
* width
* height
;
2482 if( 1 & vc_progress
->flags
) {
2483 x
+= ((vinfo
.v_width
- width
) / 2);
2484 y
+= ((vinfo
.v_height
- height
) / 2);
2486 vc_blit_rect( x
, y
, 0,
2487 width
, height
, width
, width
,
2490 | (vc_progress_angle
& kDataRotate
)
2491 | (vc_needsave
? kSave
: 0) );
2492 vc_needsave
= FALSE
;
2494 clock_deadline_for_periodic_event(vc_progress_interval
, mach_absolute_time(), &vc_progress_deadline
);
2495 thread_call_enter_delayed(&vc_progress_call
, vc_progress_deadline
);
2497 simple_unlock(&vc_progress_lock
);
2502 * Generic Console (Front-End): Master Control
2503 * -------------------------------------------
2506 #if defined (__i386__) || defined (__x86_64__)
2507 #include <pexpert/i386/boot.h>
2510 static boolean_t gc_acquired
= FALSE
;
2511 static boolean_t gc_graphics_boot
= FALSE
;
2512 static boolean_t gc_desire_text
= FALSE
;
2514 static uint64_t lastVideoPhys
= 0;
2515 static vm_offset_t lastVideoVirt
= 0;
2516 static vm_size_t lastVideoSize
= 0;
2517 static boolean_t lastVideoMapped
= FALSE
;
2520 gc_pause( boolean_t pause
, boolean_t graphics_now
)
2525 VCPUTC_LOCK_LOCK( );
2527 disableConsoleOutput
= (pause
&& !console_is_serial());
2528 gc_enabled
= (!pause
&& !graphics_now
);
2530 VCPUTC_LOCK_UNLOCK( );
2532 simple_lock(&vc_progress_lock
);
2534 vc_progress_enable
= gc_graphics_boot
&& !gc_desire_text
&& !pause
;
2535 if (vc_progress_enable
)
2536 thread_call_enter_delayed(&vc_progress_call
, vc_progress_deadline
);
2538 simple_unlock(&vc_progress_lock
);
2543 vc_initialize(__unused
struct vc_info
* vinfo_p
)
2546 vinfo
.v_rows
= vinfo
.v_height
/ ISO_CHAR_HEIGHT
;
2547 vinfo
.v_columns
= vinfo
.v_width
/ ISO_CHAR_WIDTH
;
2548 vinfo
.v_rowscanbytes
= ((vinfo
.v_depth
+ 7) / 8) * vinfo
.v_width
;
2549 vc_uiselect
= (2 == vinfo
.v_scale
) ? 1 : 0;
2553 initialize_screen(PE_Video
* boot_vinfo
, unsigned int op
)
2555 unsigned int fbsize
= 0;
2556 vm_offset_t newVideoVirt
= 0;
2557 boolean_t graphics_now
;
2562 struct vc_info new_vinfo
= vinfo
;
2564 * First, check if we are changing the size and/or location of the framebuffer
2566 new_vinfo
.v_name
[0] = 0;
2567 new_vinfo
.v_physaddr
= boot_vinfo
->v_baseAddr
& ~3; /* Get the physical address */
2569 new_vinfo
.v_physaddr
|= (((uint64_t) boot_vinfo
->v_baseAddrHigh
) << 32);
2571 if (kPEBaseAddressChange
!= op
)
2573 new_vinfo
.v_width
= (unsigned int)boot_vinfo
->v_width
;
2574 new_vinfo
.v_height
= (unsigned int)boot_vinfo
->v_height
;
2575 new_vinfo
.v_depth
= (unsigned int)boot_vinfo
->v_depth
;
2576 new_vinfo
.v_rowbytes
= (unsigned int)boot_vinfo
->v_rowBytes
;
2577 #if defined(__i386__) || defined(__x86_64__)
2578 new_vinfo
.v_type
= (unsigned int)boot_vinfo
->v_display
;
2580 new_vinfo
.v_type
= 0;
2582 unsigned int scale
= (unsigned int)boot_vinfo
->v_scale
;
2583 if (scale
== kPEScaleFactor1x
)
2584 new_vinfo
.v_scale
= kPEScaleFactor1x
;
2585 else if (scale
== kPEScaleFactor2x
)
2586 new_vinfo
.v_scale
= kPEScaleFactor2x
;
2587 else /* Scale factor not set, default to 1x */
2588 new_vinfo
.v_scale
= kPEScaleFactor1x
;
2592 if (!lastVideoMapped
)
2593 kprintf("initialize_screen: b=%08llX, w=%08X, h=%08X, r=%08X, d=%08X\n", /* (BRINGUP) */
2594 new_vinfo
.v_physaddr
, new_vinfo
.v_width
, new_vinfo
.v_height
, new_vinfo
.v_rowbytes
, new_vinfo
.v_type
); /* (BRINGUP) */
2596 if (!new_vinfo
.v_physaddr
) /* Check to see if we have a framebuffer */
2598 kprintf("initialize_screen: No video - forcing serial mode\n"); /* (BRINGUP) */
2599 new_vinfo
.v_depth
= 0; /* vc routines are nop */
2600 (void)switch_to_serial_console(); /* Switch into serial mode */
2601 gc_graphics_boot
= FALSE
; /* Say we are not in graphics mode */
2602 disableConsoleOutput
= FALSE
; /* Allow printfs to happen */
2608 * If VM is up, we are given a virtual address, unless b0 is set to indicate physical.
2610 if ((kernel_map
!= VM_MAP_NULL
) && (0 == (1 & boot_vinfo
->v_baseAddr
)))
2612 fbppage
= pmap_find_phys(kernel_pmap
, (addr64_t
)boot_vinfo
->v_baseAddr
); /* Get the physical address of frame buffer */
2613 if(!fbppage
) /* Did we find it? */
2615 panic("initialize_screen: Strange framebuffer - addr = %08X\n", (uint32_t)boot_vinfo
->v_baseAddr
);
2617 new_vinfo
.v_physaddr
= (((uint64_t)fbppage
) << 12) | (boot_vinfo
->v_baseAddr
& PAGE_MASK
); /* Get the physical address */
2620 if (boot_vinfo
->v_length
!= 0)
2621 fbsize
= (unsigned int) round_page(boot_vinfo
->v_length
);
2623 fbsize
= (unsigned int) round_page(new_vinfo
.v_height
* new_vinfo
.v_rowbytes
); /* Remember size */
2626 if ((lastVideoPhys
!= new_vinfo
.v_physaddr
) || (fbsize
> lastVideoSize
)) /* Did framebuffer change location or get bigger? */
2628 unsigned int flags
= VM_WIMG_IO
;
2629 newVideoVirt
= io_map_spec((vm_map_offset_t
)new_vinfo
.v_physaddr
, fbsize
, flags
); /* Allocate address space for framebuffer */
2633 if (newVideoVirt
!= 0)
2634 new_vinfo
.v_baseaddr
= newVideoVirt
+ boot_vinfo
->v_offset
; /* Set the new framebuffer address */
2636 new_vinfo
.v_baseaddr
= lastVideoVirt
+ boot_vinfo
->v_offset
; /* Set the new framebuffer address */
2638 #if defined(__x86_64__)
2639 // Adjust the video buffer pointer to point to where it is in high virtual (above the hole)
2640 new_vinfo
.v_baseaddr
|= (VM_MIN_KERNEL_ADDRESS
& ~LOW_4GB_MASK
);
2643 /* Update the vinfo structure atomically with respect to the vc_progress task if running */
2646 simple_lock(&vc_progress_lock
);
2648 simple_unlock(&vc_progress_lock
);
2655 // If we changed the virtual address, remove the old mapping
2656 if (newVideoVirt
!= 0)
2658 if (lastVideoVirt
) /* Was the framebuffer mapped before? */
2661 if(lastVideoMapped
) /* Was this not a special pre-VM mapping? */
2664 pmap_remove(kernel_pmap
, trunc_page_64(lastVideoVirt
),
2665 round_page_64(lastVideoVirt
+ lastVideoSize
)); /* Toss mappings */
2667 if(lastVideoMapped
) /* Was this not a special pre-VM mapping? */
2669 kmem_free(kernel_map
, lastVideoVirt
, lastVideoSize
); /* Toss kernel addresses */
2672 lastVideoPhys
= new_vinfo
.v_physaddr
; /* Remember the framebuffer address */
2673 lastVideoSize
= fbsize
; /* Remember the size */
2674 lastVideoVirt
= newVideoVirt
; /* Remember the virtual framebuffer address */
2675 lastVideoMapped
= (NULL
!= kernel_map
);
2678 if (kPEBaseAddressChange
!= op
)
2680 // Graphics mode setup by the booter.
2682 gc_ops
.initialize
= vc_initialize
;
2683 gc_ops
.enable
= vc_enable
;
2684 gc_ops
.paint_char
= vc_paint_char
;
2685 gc_ops
.scroll_down
= vc_scroll_down
;
2686 gc_ops
.scroll_up
= vc_scroll_up
;
2687 gc_ops
.clear_screen
= vc_clear_screen
;
2688 gc_ops
.hide_cursor
= vc_reverse_cursor
;
2689 gc_ops
.show_cursor
= vc_reverse_cursor
;
2690 gc_ops
.update_color
= vc_update_color
;
2691 gc_initialize(&vinfo
);
2694 #ifdef GRATEFULDEBUGGER
2695 GratefulDebInit((bootBumbleC
*)boot_vinfo
); /* Re-initialize GratefulDeb */
2696 #endif /* GRATEFULDEBUGGER */
2699 graphics_now
= gc_graphics_boot
&& !gc_desire_text
;
2702 case kPEGraphicsMode
:
2703 panicDialogDesired
= TRUE
;
2704 gc_graphics_boot
= TRUE
;
2705 gc_desire_text
= FALSE
;
2709 panicDialogDesired
= FALSE
;
2710 disable_debug_output
= FALSE
;
2711 gc_graphics_boot
= FALSE
;
2714 case kPEAcquireScreen
:
2715 if ( gc_acquired
) break;
2716 vc_progress_set( graphics_now
, kProgressAcquireDelay
);
2717 gc_enable( !graphics_now
);
2719 gc_desire_text
= FALSE
;
2722 case kPEDisableScreen
:
2725 gc_pause( TRUE
, graphics_now
);
2729 case kPEEnableScreen
:
2732 gc_pause( FALSE
, graphics_now
);
2737 if ( console_is_serial() ) break;
2739 panicDialogDesired
= FALSE
;
2740 disable_debug_output
= FALSE
;
2741 if ( gc_acquired
== FALSE
)
2743 gc_desire_text
= TRUE
;
2746 if ( gc_graphics_boot
== FALSE
) break;
2748 vc_progress_set( FALSE
, 0 );
2749 #if !CONFIG_EMBEDDED
2750 vc_enable_progressmeter( FALSE
);
2755 case kPEReleaseScreen
:
2756 gc_acquired
= FALSE
;
2757 gc_desire_text
= FALSE
;
2759 if ( gc_graphics_boot
== FALSE
) break;
2761 vc_progress_set( FALSE
, 0 );
2762 #if !CONFIG_EMBEDDED
2763 vc_enable_progressmeter( FALSE
);
2767 #ifdef GRATEFULDEBUGGER
2768 GratefulDebInit(0); /* Stop grateful debugger */
2769 #endif /* GRATEFULDEBUGGER */
2772 #ifdef GRATEFULDEBUGGER
2773 if ( boot_vinfo
) GratefulDebInit((bootBumbleC
*)boot_vinfo
); /* Re initialize GratefulDeb */
2774 #endif /* GRATEFULDEBUGGER */
2780 unsigned int *p
, *endp
, *row
;
2781 int col
, rowline
, rowlongs
;
2782 register unsigned int mask
;
2787 if ( vinfo
.v_depth
== 32 )
2789 else if ( vinfo
.v_depth
== 30 )
2790 mask
= (0x1ff<<20) | (0x1ff<<10) | 0x1ff;
2791 else if ( vinfo
.v_depth
== 16 )
2796 rowline
= (int)(vinfo
.v_rowscanbytes
/ 4);
2797 rowlongs
= (int)(vinfo
.v_rowbytes
/ 4);
2799 p
= (unsigned int*) vinfo
.v_baseaddr
;
2800 endp
= p
+ (rowlongs
* vinfo
.v_height
);
2802 for (row
= p
; row
< endp
; row
+= rowlongs
) {
2803 for (p
= &row
[0], col
= 0; col
< rowline
; col
++) {
2804 *p
= (*p
>> 1) & mask
;
2810 void vcattach(void); /* XXX gcc 4 warning cleanup */
2815 vm_initialized
= TRUE
;
2817 if ( gc_graphics_boot
== FALSE
)
2823 initialize_screen(NULL
, kPEReleaseScreen
);
2826 initialize_screen(NULL
, kPEAcquireScreen
);
2828 for ( index
= 0 ; index
< msgbufp
->msg_bufx
; index
++ )
2830 if (msgbufp
->msg_bufc
[index
] == '\0') {
2834 vcputc( 0, 0, msgbufp
->msg_bufc
[index
] );
2836 if ( msgbufp
->msg_bufc
[index
] == '\n' )
2838 vcputc( 0, 0,'\r' );
2844 #if !CONFIG_EMBEDDED
2846 int vc_progress_meter_enable
;
2847 int vc_progress_meter_value
;
2849 static void * vc_progress_meter_backbuffer
;
2850 static int vc_progress_meter_drawn
;
2853 vc_draw_progress_meter(int select
, unsigned int flags
, int x1
, int x2
)
2855 const unsigned char * data
;
2859 ox
= ((vinfo
.v_width
- (kProgressBarWidth
<< vc_uiselect
)) / 2);
2860 oy
= vinfo
.v_height
- (((vinfo
.v_height
/ 2) - ((vc_progress
->dy
+ kProgressBarHeight
) << vc_uiselect
)) / 2);
2862 if (kDataBack
== flags
)
2864 // restore back bits
2865 vc_blit_rect(ox
+ x1
, oy
, x1
,
2866 x2
, (kProgressBarHeight
<< vc_uiselect
), 0, (kProgressBarWidth
<< vc_uiselect
),
2867 NULL
, vc_progress_meter_backbuffer
, flags
);
2871 for (x
= x1
; x
< x2
; x
+= w
)
2873 if (x
< (kProgressBarCapWidth
<< vc_uiselect
))
2875 if (x2
< (kProgressBarCapWidth
<< vc_uiselect
))
2878 w
= (kProgressBarCapWidth
<< vc_uiselect
) - x
;
2879 data
= progressmeter_leftcap
[vc_uiselect
& 1][select
& 1];
2881 vc_blit_rect(ox
+ x
, oy
, x
, w
,
2882 (kProgressBarHeight
<< vc_uiselect
),
2883 (kProgressBarCapWidth
<< vc_uiselect
),
2884 (kProgressBarWidth
<< vc_uiselect
),
2885 data
, vc_progress_meter_backbuffer
, flags
);
2887 else if (x
< ((kProgressBarWidth
- kProgressBarCapWidth
) << vc_uiselect
))
2889 if (x2
< ((kProgressBarWidth
- kProgressBarCapWidth
) << vc_uiselect
))
2892 w
= ((kProgressBarWidth
- kProgressBarCapWidth
) << vc_uiselect
) - x
;
2893 data
= progressmeter_middle
[vc_uiselect
& 1][select
& 1];
2894 vc_blit_rect(ox
+ x
, oy
, x
, w
,
2895 (kProgressBarHeight
<< vc_uiselect
),
2897 (kProgressBarWidth
<< vc_uiselect
),
2898 data
, vc_progress_meter_backbuffer
, flags
);
2903 data
= progressmeter_rightcap
[vc_uiselect
& 1][select
& 1];
2904 data
+= x
- ((kProgressBarWidth
- kProgressBarCapWidth
) << vc_uiselect
);
2905 vc_blit_rect(ox
+ x
, oy
, x
, w
,
2906 (kProgressBarHeight
<< vc_uiselect
),
2907 (kProgressBarCapWidth
<< vc_uiselect
),
2908 (kProgressBarWidth
<< vc_uiselect
),
2909 data
, vc_progress_meter_backbuffer
, flags
);
2915 vc_enable_progressmeter(int new_value
)
2918 void * new_buffer
= NULL
;
2921 new_buffer
= kalloc((kProgressBarWidth
<< vc_uiselect
)
2922 * (kProgressBarHeight
<< vc_uiselect
) * sizeof(int));
2925 simple_lock(&vc_progress_lock
);
2927 if (gc_enabled
|| !gc_acquired
|| !gc_graphics_boot
)
2930 if (new_value
!= vc_progress_meter_enable
)
2934 vc_progress_meter_backbuffer
= new_buffer
;
2935 vc_draw_progress_meter(FALSE
, kDataAlpha
| kSave
, 0, (kProgressBarWidth
<< vc_uiselect
));
2936 vc_progress_meter_enable
= TRUE
;
2938 vc_progress_meter_drawn
= 0;
2940 else if (vc_progress_meter_backbuffer
)
2942 vc_draw_progress_meter(0, kDataBack
, 0, (kProgressBarWidth
<< vc_uiselect
));
2943 new_buffer
= vc_progress_meter_backbuffer
;
2944 vc_progress_meter_backbuffer
= NULL
;
2945 vc_progress_meter_enable
= FALSE
;
2949 simple_unlock(&vc_progress_lock
);
2953 kfree(new_buffer
, (kProgressBarWidth
<< vc_uiselect
)
2954 * (kProgressBarHeight
<< vc_uiselect
) * sizeof(int));
2958 vc_set_progressmeter(int new_value
)
2963 if ((new_value
< 0) | (new_value
> 100))
2967 simple_lock(&vc_progress_lock
);
2969 if (vc_progress_meter_enable
)
2971 vc_progress_meter_value
= new_value
;
2972 x2
= ((kProgressBarWidth
<< vc_uiselect
) * new_value
) / 100;
2973 if (x2
> vc_progress_meter_drawn
)
2974 vc_draw_progress_meter(TRUE
, kDataAlpha
, vc_progress_meter_drawn
, x2
);
2976 vc_draw_progress_meter(FALSE
, kDataAlpha
, x2
, vc_progress_meter_drawn
);
2977 vc_progress_meter_drawn
= x2
;
2980 simple_unlock(&vc_progress_lock
);
2984 #endif /* !CONFIG_EMBEDDED */