]> git.saurik.com Git - apple/xnu.git/blob - osfmk/console/video_console.c
2034f1e51755faacc551a9e3411b33935e06dd9a
[apple/xnu.git] / osfmk / console / video_console.c
1 /*
2 * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_FREE_COPYRIGHT@
30 *
31 */
32 /*
33 * @APPLE_FREE_COPYRIGHT@
34 */
35 /*
36 * NetBSD: ite.c,v 1.16 1995/07/17 01:24:34 briggs Exp
37 *
38 * Copyright (c) 1988 University of Utah.
39 * Copyright (c) 1990, 1993
40 * The Regents of the University of California. All rights reserved.
41 *
42 * This code is derived from software contributed to Berkeley by
43 * the Systems Programming Group of the University of Utah Computer
44 * Science Department.
45 *
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
48 * are met:
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.
61 *
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
72 * SUCH DAMAGE.
73 *
74 * from: Utah $Hdr: ite.c 1.28 92/12/20$
75 *
76 * @(#)ite.c 8.2 (Berkeley) 1/12/94
77 */
78
79 /*
80 * ite.c
81 *
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.
86 *
87 * -- Brad and Lawrence, June 26th, 1994
88 *
89 */
90
91 #include <console/video_console.h>
92 #include <console/serial_protos.h>
93
94 #include <kern/kern_types.h>
95 #include <kern/kalloc.h>
96 #include <kern/debug.h>
97 #include <kern/spl.h>
98 #include <kern/thread_call.h>
99
100 #include <vm/pmap.h>
101 #include <vm/vm_kern.h>
102 #include <machine/io_map_entries.h>
103 #include <machine/machine_cpu.h>
104
105 #include <pexpert/pexpert.h>
106 #include <sys/kdebug.h>
107
108 #include "iso_font.c"
109 #if !CONFIG_EMBEDDED
110 #include "progress_meter_data.c"
111 #endif
112
113 #include "sys/msgbuf.h"
114
115 /*
116 * Generic Console (Front-End)
117 * ---------------------------
118 */
119
120 struct vc_info vinfo;
121
122 void noroot_icon_test(void);
123
124
125 extern int disableConsoleOutput;
126 static boolean_t gc_enabled = FALSE;
127 static boolean_t gc_initialized = FALSE;
128 static boolean_t vm_initialized = FALSE;
129
130 static struct {
131 void (*initialize)(struct vc_info * info);
132 void (*enable)(boolean_t enable);
133 void (*paint_char)(unsigned int xx, unsigned int yy, unsigned char ch,
134 int attrs, unsigned char ch_previous,
135 int attrs_previous);
136 void (*clear_screen)(unsigned int xx, unsigned int yy, unsigned int top,
137 unsigned int bottom, int which);
138 void (*scroll_down)(int num, unsigned int top, unsigned int bottom);
139 void (*scroll_up)(int num, unsigned int top, unsigned int bottom);
140 void (*hide_cursor)(unsigned int xx, unsigned int yy);
141 void (*show_cursor)(unsigned int xx, unsigned int yy);
142 void (*update_color)(int color, boolean_t fore);
143 } gc_ops;
144
145 static unsigned char *gc_buffer_attributes;
146 static unsigned char *gc_buffer_characters;
147 static unsigned char *gc_buffer_colorcodes;
148 static unsigned char *gc_buffer_tab_stops;
149 static uint32_t gc_buffer_columns;
150 static uint32_t gc_buffer_rows;
151 static uint32_t gc_buffer_size;
152
153 #if defined(__i386__) || defined(__x86_64__)
154 decl_simple_lock_data(static, vcputc_lock);
155
156 #define VCPUTC_LOCK_INIT() \
157 MACRO_BEGIN \
158 simple_lock_init(&vcputc_lock, 0); \
159 MACRO_END
160
161 #define VCPUTC_LOCK_LOCK() \
162 MACRO_BEGIN \
163 boolean_t istate = ml_get_interrupts_enabled(); \
164 while (!simple_lock_try(&vcputc_lock, LCK_GRP_NULL)) \
165 { \
166 if (!istate) \
167 handle_pending_TLB_flushes(); \
168 cpu_pause(); \
169 } \
170 MACRO_END
171
172 #define VCPUTC_LOCK_UNLOCK() \
173 MACRO_BEGIN \
174 simple_unlock(&vcputc_lock); \
175 MACRO_END
176 #else
177 static hw_lock_data_t vcputc_lock;
178
179 #define VCPUTC_LOCK_INIT() \
180 MACRO_BEGIN \
181 hw_lock_init(&vcputc_lock); \
182 MACRO_END
183
184 #define VCPUTC_LOCK_LOCK() \
185 MACRO_BEGIN \
186 if (!hw_lock_to(&vcputc_lock, ~0U, LCK_GRP_NULL))\
187 { \
188 panic("VCPUTC_LOCK_LOCK"); \
189 } \
190 MACRO_END
191
192 #define VCPUTC_LOCK_UNLOCK() \
193 MACRO_BEGIN \
194 hw_lock_unlock(&vcputc_lock); \
195 MACRO_END
196 #endif
197
198 /*
199 # Attribute codes:
200 # 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
201 # Text color codes:
202 # 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
203 # Background color codes:
204 # 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
205 */
206
207 #define ATTR_NONE 0
208 #define ATTR_BOLD 1
209 #define ATTR_UNDER 2
210 #define ATTR_REVERSE 4
211
212 #define COLOR_BACKGROUND 0
213 #define COLOR_FOREGROUND 7
214
215 #define COLOR_CODE_GET(code, fore) (((code) & ((fore) ? 0xF0 : 0x0F)) >> ((fore) ? 4 : 0))
216 #define COLOR_CODE_SET(code, color, fore) (((code) & ((fore) ? 0x0F : 0xF0)) | ((color) << ((fore) ? 4 : 0)))
217
218 static unsigned char gc_color_code;
219
220 /* VT100 state: */
221 #define MAXPARS 16
222 static unsigned int gc_x, gc_y, gc_savex, gc_savey;
223 static unsigned int gc_par[MAXPARS], gc_numpars, gc_hanging_cursor, gc_attr, gc_saveattr;
224
225 /* VT100 scroll region */
226 static unsigned int gc_scrreg_top, gc_scrreg_bottom;
227
228 enum vt100state_e {
229 ESnormal, /* Nothing yet */
230 ESesc, /* Got ESC */
231 ESsquare, /* Got ESC [ */
232 ESgetpars, /* About to get or getting the parameters */
233 ESgotpars, /* Finished getting the parameters */
234 ESfunckey, /* Function key */
235 EShash, /* DEC-specific stuff (screen align, etc.) */
236 ESsetG0, /* Specify the G0 character set */
237 ESsetG1, /* Specify the G1 character set */
238 ESask,
239 EScharsize,
240 ESignore /* Ignore this sequence */
241 } gc_vt100state = ESnormal;
242
243
244 enum
245 {
246 /* secs */
247 kProgressAcquireDelay = 0,
248 #if CONFIG_EMBEDDED
249 kProgressReacquireDelay = 5,
250 #else
251 kProgressReacquireDelay = 5,
252 #endif
253 };
254
255 static int8_t vc_rotate_matr[4][2][2] = {
256 { { 1, 0 },
257 { 0, 1 } },
258 { { 0, 1 },
259 { -1, 0 } },
260 { { -1, 0 },
261 { 0, -1 } },
262 { { 0, -1 },
263 { 1, 0 } }
264 };
265
266 static int gc_wrap_mode = 1, gc_relative_origin = 0;
267 static int gc_charset_select = 0, gc_save_charset_s = 0;
268 static int gc_charset[2] = { 0, 0 };
269 static int gc_charset_save[2] = { 0, 0 };
270
271 static void gc_clear_line(unsigned int xx, unsigned int yy, int which);
272 static void gc_clear_screen(unsigned int xx, unsigned int yy, int top,
273 unsigned int bottom, int which);
274 static void gc_enable(boolean_t enable);
275 static void gc_hide_cursor(unsigned int xx, unsigned int yy);
276 static void gc_initialize(struct vc_info * info);
277 static boolean_t gc_is_tab_stop(unsigned int column);
278 static void gc_paint_char(unsigned int xx, unsigned int yy, unsigned char ch,
279 int attrs);
280 static void gc_putchar(char ch);
281 static void gc_putc_askcmd(unsigned char ch);
282 static void gc_putc_charsetcmd(int charset, unsigned char ch);
283 static void gc_putc_charsizecmd(unsigned char ch);
284 static void gc_putc_esc(unsigned char ch);
285 static void gc_putc_getpars(unsigned char ch);
286 static void gc_putc_gotpars(unsigned char ch);
287 static void gc_putc_normal(unsigned char ch);
288 static void gc_putc_square(unsigned char ch);
289 static void gc_reset_screen(void);
290 static void gc_reset_tabs(void);
291 static void gc_reset_vt100(void);
292 static void gc_scroll_down(int num, unsigned int top, unsigned int bottom);
293 static void gc_scroll_up(int num, unsigned int top, unsigned int bottom);
294 static void gc_set_tab_stop(unsigned int column, boolean_t enabled);
295 static void gc_show_cursor(unsigned int xx, unsigned int yy);
296 static void gc_update_color(int color, boolean_t fore);
297
298 static void
299 gc_clear_line(unsigned int xx, unsigned int yy, int which)
300 {
301 unsigned int start, end, i;
302
303 /*
304 * This routine runs extremely slowly. I don't think it's
305 * used all that often, except for To end of line. I'll go
306 * back and speed this up when I speed up the whole vc
307 * module. --LK
308 */
309
310 switch (which) {
311 case 0: /* To end of line */
312 start = xx;
313 end = vinfo.v_columns-1;
314 break;
315 case 1: /* To start of line */
316 start = 0;
317 end = xx;
318 break;
319 case 2: /* Whole line */
320 start = 0;
321 end = vinfo.v_columns-1;
322 break;
323 default:
324 return;
325 }
326
327 for (i = start; i <= end; i++) {
328 gc_paint_char(i, yy, ' ', ATTR_NONE);
329 }
330 }
331
332 static void
333 gc_clear_screen(unsigned int xx, unsigned int yy, int top, unsigned int bottom,
334 int which)
335 {
336 if (!gc_buffer_size) return;
337
338 if ( xx < gc_buffer_columns && yy < gc_buffer_rows && bottom <= gc_buffer_rows )
339 {
340 uint32_t start, end;
341
342 switch (which) {
343 case 0: /* To end of screen */
344 start = (yy * gc_buffer_columns) + xx;
345 end = (bottom * gc_buffer_columns) - 1;
346 break;
347 case 1: /* To start of screen */
348 start = (top * gc_buffer_columns);
349 end = (yy * gc_buffer_columns) + xx;
350 break;
351 case 2: /* Whole screen */
352 start = (top * gc_buffer_columns);
353 end = (bottom * gc_buffer_columns) - 1;
354 break;
355 default:
356 start = 0;
357 end = 0;
358 break;
359 }
360
361 memset(gc_buffer_attributes + start, ATTR_NONE, end - start + 1);
362 memset(gc_buffer_characters + start, ' ', end - start + 1);
363 memset(gc_buffer_colorcodes + start, gc_color_code, end - start + 1);
364 }
365
366 gc_ops.clear_screen(xx, yy, top, bottom, which);
367 }
368
369 static void
370 gc_enable( boolean_t enable )
371 {
372 unsigned char *buffer_attributes = NULL;
373 unsigned char *buffer_characters = NULL;
374 unsigned char *buffer_colorcodes = NULL;
375 unsigned char *buffer_tab_stops = NULL;
376 uint32_t buffer_columns = 0;
377 uint32_t buffer_rows = 0;
378 uint32_t buffer_size = 0;
379 spl_t s;
380
381 if ( enable == FALSE )
382 {
383 // only disable console output if it goes to the graphics console
384 if ( console_is_serial() == FALSE )
385 disableConsoleOutput = TRUE;
386 gc_enabled = FALSE;
387 gc_ops.enable(FALSE);
388 }
389
390 s = splhigh( );
391 VCPUTC_LOCK_LOCK( );
392
393 if ( gc_buffer_size )
394 {
395 buffer_attributes = gc_buffer_attributes;
396 buffer_characters = gc_buffer_characters;
397 buffer_colorcodes = gc_buffer_colorcodes;
398 buffer_tab_stops = gc_buffer_tab_stops;
399 buffer_columns = gc_buffer_columns;
400 buffer_rows = gc_buffer_rows;
401 buffer_size = gc_buffer_size;
402
403 gc_buffer_attributes = NULL;
404 gc_buffer_characters = NULL;
405 gc_buffer_colorcodes = NULL;
406 gc_buffer_tab_stops = NULL;
407 gc_buffer_columns = 0;
408 gc_buffer_rows = 0;
409 gc_buffer_size = 0;
410
411 VCPUTC_LOCK_UNLOCK( );
412 splx( s );
413
414 kfree( buffer_attributes, buffer_size );
415 kfree( buffer_characters, buffer_size );
416 kfree( buffer_colorcodes, buffer_size );
417 kfree( buffer_tab_stops, buffer_columns );
418 }
419 else
420 {
421 VCPUTC_LOCK_UNLOCK( );
422 splx( s );
423 }
424
425 if ( enable )
426 {
427 if ( vm_initialized )
428 {
429 buffer_columns = vinfo.v_columns;
430 buffer_rows = vinfo.v_rows;
431 buffer_size = buffer_columns * buffer_rows;
432
433 if ( buffer_size )
434 {
435 buffer_attributes = (unsigned char *) kalloc( buffer_size );
436 buffer_characters = (unsigned char *) kalloc( buffer_size );
437 buffer_colorcodes = (unsigned char *) kalloc( buffer_size );
438 buffer_tab_stops = (unsigned char *) kalloc( buffer_columns );
439
440 if ( buffer_attributes == NULL ||
441 buffer_characters == NULL ||
442 buffer_colorcodes == NULL ||
443 buffer_tab_stops == NULL )
444 {
445 if ( buffer_attributes ) kfree( buffer_attributes, buffer_size );
446 if ( buffer_characters ) kfree( buffer_characters, buffer_size );
447 if ( buffer_colorcodes ) kfree( buffer_colorcodes, buffer_size );
448 if ( buffer_tab_stops ) kfree( buffer_tab_stops, buffer_columns );
449
450 buffer_attributes = NULL;
451 buffer_characters = NULL;
452 buffer_colorcodes = NULL;
453 buffer_tab_stops = NULL;
454 buffer_columns = 0;
455 buffer_rows = 0;
456 buffer_size = 0;
457 }
458 else
459 {
460 memset( buffer_attributes, ATTR_NONE, buffer_size );
461 memset( buffer_characters, ' ', buffer_size );
462 memset( buffer_colorcodes, COLOR_CODE_SET( 0, COLOR_FOREGROUND, TRUE ), buffer_size );
463 memset( buffer_tab_stops, 0, buffer_columns );
464 }
465 }
466 }
467
468 s = splhigh( );
469 VCPUTC_LOCK_LOCK( );
470
471 gc_buffer_attributes = buffer_attributes;
472 gc_buffer_characters = buffer_characters;
473 gc_buffer_colorcodes = buffer_colorcodes;
474 gc_buffer_tab_stops = buffer_tab_stops;
475 gc_buffer_columns = buffer_columns;
476 gc_buffer_rows = buffer_rows;
477 gc_buffer_size = buffer_size;
478
479 gc_reset_screen();
480
481 VCPUTC_LOCK_UNLOCK( );
482 splx( s );
483
484 gc_ops.clear_screen(gc_x, gc_y, 0, vinfo.v_rows, 2);
485 gc_ops.show_cursor(gc_x, gc_y);
486
487 gc_ops.enable(TRUE);
488 gc_enabled = TRUE;
489 disableConsoleOutput = FALSE;
490 }
491 }
492
493 static void
494 gc_hide_cursor(unsigned int xx, unsigned int yy)
495 {
496 if ( xx < gc_buffer_columns && yy < gc_buffer_rows )
497 {
498 uint32_t index = (yy * gc_buffer_columns) + xx;
499 unsigned char attribute = gc_buffer_attributes[index];
500 unsigned char character = gc_buffer_characters[index];
501 unsigned char colorcode = gc_buffer_colorcodes[index];
502 unsigned char colorcodesave = gc_color_code;
503
504 gc_update_color(COLOR_CODE_GET(colorcode, TRUE ), TRUE );
505 gc_update_color(COLOR_CODE_GET(colorcode, FALSE), FALSE);
506
507 gc_ops.paint_char(xx, yy, character, attribute, 0, 0);
508
509 gc_update_color(COLOR_CODE_GET(colorcodesave, TRUE ), TRUE );
510 gc_update_color(COLOR_CODE_GET(colorcodesave, FALSE), FALSE);
511 }
512 else
513 {
514 gc_ops.hide_cursor(xx, yy);
515 }
516 }
517
518 static void
519 gc_initialize(struct vc_info * info)
520 {
521 if ( gc_initialized == FALSE )
522 {
523 /* Init our lock */
524 VCPUTC_LOCK_INIT();
525
526 gc_initialized = TRUE;
527 }
528
529 gc_ops.initialize(info);
530
531 gc_reset_vt100();
532 gc_x = gc_y = 0;
533 }
534
535 static void
536 gc_paint_char(unsigned int xx, unsigned int yy, unsigned char ch, int attrs)
537 {
538 if ( xx < gc_buffer_columns && yy < gc_buffer_rows )
539 {
540 uint32_t index = (yy * gc_buffer_columns) + xx;
541
542 gc_buffer_attributes[index] = attrs;
543 gc_buffer_characters[index] = ch;
544 gc_buffer_colorcodes[index] = gc_color_code;
545 }
546
547 gc_ops.paint_char(xx, yy, ch, attrs, 0, 0);
548 }
549
550 static void
551 gc_putchar(char ch)
552 {
553 if (!ch) {
554 return; /* ignore null characters */
555 }
556 switch (gc_vt100state) {
557 default:gc_vt100state = ESnormal; /* FALLTHROUGH */
558 case ESnormal:
559 gc_putc_normal(ch);
560 break;
561 case ESesc:
562 gc_putc_esc(ch);
563 break;
564 case ESsquare:
565 gc_putc_square(ch);
566 break;
567 case ESgetpars:
568 gc_putc_getpars(ch);
569 break;
570 case ESgotpars:
571 gc_putc_gotpars(ch);
572 break;
573 case ESask:
574 gc_putc_askcmd(ch);
575 break;
576 case EScharsize:
577 gc_putc_charsizecmd(ch);
578 break;
579 case ESsetG0:
580 gc_putc_charsetcmd(0, ch);
581 break;
582 case ESsetG1:
583 gc_putc_charsetcmd(1, ch);
584 break;
585 }
586
587 if (gc_x >= vinfo.v_columns) {
588 if (0 == vinfo.v_columns)
589 gc_x = 0;
590 else
591 gc_x = vinfo.v_columns - 1;
592 }
593 if (gc_y >= vinfo.v_rows) {
594 if (0 == vinfo.v_rows)
595 gc_y = 0;
596 else
597 gc_y = vinfo.v_rows - 1;
598 }
599 }
600
601 static void
602 gc_putc_askcmd(unsigned char ch)
603 {
604 if (ch >= '0' && ch <= '9') {
605 gc_par[gc_numpars] = (10*gc_par[gc_numpars]) + (ch-'0');
606 return;
607 }
608 gc_vt100state = ESnormal;
609
610 switch (gc_par[0]) {
611 case 6:
612 gc_relative_origin = ch == 'h';
613 break;
614 case 7: /* wrap around mode h=1, l=0*/
615 gc_wrap_mode = ch == 'h';
616 break;
617 default:
618 break;
619 }
620
621 }
622
623 static void
624 gc_putc_charsetcmd(int charset, unsigned char ch)
625 {
626 gc_vt100state = ESnormal;
627
628 switch (ch) {
629 case 'A' :
630 case 'B' :
631 default:
632 gc_charset[charset] = 0;
633 break;
634 case '0' : /* Graphic characters */
635 case '2' :
636 gc_charset[charset] = 0x21;
637 break;
638 }
639
640 }
641
642 static void
643 gc_putc_charsizecmd(unsigned char ch)
644 {
645 gc_vt100state = ESnormal;
646
647 switch (ch) {
648 case '3' :
649 case '4' :
650 case '5' :
651 case '6' :
652 break;
653 case '8' : /* fill 'E's */
654 {
655 unsigned int xx, yy;
656 for (yy = 0; yy < vinfo.v_rows; yy++)
657 for (xx = 0; xx < vinfo.v_columns; xx++)
658 gc_paint_char(xx, yy, 'E', ATTR_NONE);
659 }
660 break;
661 }
662
663 }
664
665 static void
666 gc_putc_esc(unsigned char ch)
667 {
668 gc_vt100state = ESnormal;
669
670 switch (ch) {
671 case '[':
672 gc_vt100state = ESsquare;
673 break;
674 case 'c': /* Reset terminal */
675 gc_reset_vt100();
676 gc_clear_screen(gc_x, gc_y, 0, vinfo.v_rows, 2);
677 gc_x = gc_y = 0;
678 break;
679 case 'D': /* Line feed */
680 case 'E':
681 if (gc_y >= gc_scrreg_bottom -1) {
682 gc_scroll_up(1, gc_scrreg_top, gc_scrreg_bottom);
683 gc_y = gc_scrreg_bottom - 1;
684 } else {
685 gc_y++;
686 }
687 if (ch == 'E') gc_x = 0;
688 break;
689 case 'H': /* Set tab stop */
690 gc_set_tab_stop(gc_x, TRUE);
691 break;
692 case 'M': /* Cursor up */
693 if (gc_y <= gc_scrreg_top) {
694 gc_scroll_down(1, gc_scrreg_top, gc_scrreg_bottom);
695 gc_y = gc_scrreg_top;
696 } else {
697 gc_y--;
698 }
699 break;
700 case '>':
701 gc_reset_vt100();
702 break;
703 case '7': /* Save cursor */
704 gc_savex = gc_x;
705 gc_savey = gc_y;
706 gc_saveattr = gc_attr;
707 gc_save_charset_s = gc_charset_select;
708 gc_charset_save[0] = gc_charset[0];
709 gc_charset_save[1] = gc_charset[1];
710 break;
711 case '8': /* Restore cursor */
712 gc_x = gc_savex;
713 gc_y = gc_savey;
714 gc_attr = gc_saveattr;
715 gc_charset_select = gc_save_charset_s;
716 gc_charset[0] = gc_charset_save[0];
717 gc_charset[1] = gc_charset_save[1];
718 break;
719 case 'Z': /* return terminal ID */
720 break;
721 case '#': /* change characters height */
722 gc_vt100state = EScharsize;
723 break;
724 case '(':
725 gc_vt100state = ESsetG0;
726 break;
727 case ')': /* character set sequence */
728 gc_vt100state = ESsetG1;
729 break;
730 case '=':
731 break;
732 default:
733 /* Rest not supported */
734 break;
735 }
736
737 }
738
739 static void
740 gc_putc_getpars(unsigned char ch)
741 {
742 if (ch == '?') {
743 gc_vt100state = ESask;
744 return;
745 }
746 if (ch == '[') {
747 gc_vt100state = ESnormal;
748 /* Not supported */
749 return;
750 }
751 if (ch == ';' && gc_numpars < MAXPARS - 1) {
752 gc_numpars++;
753 } else
754 if (ch >= '0' && ch <= '9') {
755 gc_par[gc_numpars] *= 10;
756 gc_par[gc_numpars] += ch - '0';
757 } else {
758 gc_numpars++;
759 gc_vt100state = ESgotpars;
760 gc_putc_gotpars(ch);
761 }
762 }
763
764 static void
765 gc_putc_gotpars(unsigned char ch)
766 {
767 unsigned int i;
768
769 if (ch < ' ') {
770 /* special case for vttest for handling cursor
771 movement in escape sequences */
772 gc_putc_normal(ch);
773 gc_vt100state = ESgotpars;
774 return;
775 }
776 gc_vt100state = ESnormal;
777 switch (ch) {
778 case 'A': /* Up */
779 gc_y -= gc_par[0] ? gc_par[0] : 1;
780 if (gc_y < gc_scrreg_top)
781 gc_y = gc_scrreg_top;
782 break;
783 case 'B': /* Down */
784 gc_y += gc_par[0] ? gc_par[0] : 1;
785 if (gc_y >= gc_scrreg_bottom)
786 gc_y = gc_scrreg_bottom - 1;
787 break;
788 case 'C': /* Right */
789 gc_x += gc_par[0] ? gc_par[0] : 1;
790 if (gc_x >= vinfo.v_columns)
791 gc_x = vinfo.v_columns-1;
792 break;
793 case 'D': /* Left */
794 if (gc_par[0] > gc_x)
795 gc_x = 0;
796 else if (gc_par[0])
797 gc_x -= gc_par[0];
798 else if (gc_x)
799 --gc_x;
800 break;
801 case 'H': /* Set cursor position */
802 case 'f':
803 gc_x = gc_par[1] ? gc_par[1] - 1 : 0;
804 gc_y = gc_par[0] ? gc_par[0] - 1 : 0;
805 if (gc_relative_origin)
806 gc_y += gc_scrreg_top;
807 gc_hanging_cursor = 0;
808 break;
809 case 'X': /* clear p1 characters */
810 if (gc_numpars) {
811 for (i = gc_x; i < gc_x + gc_par[0]; i++)
812 gc_paint_char(i, gc_y, ' ', ATTR_NONE);
813 }
814 break;
815 case 'J': /* Clear part of screen */
816 gc_clear_screen(gc_x, gc_y, 0, vinfo.v_rows, gc_par[0]);
817 break;
818 case 'K': /* Clear part of line */
819 gc_clear_line(gc_x, gc_y, gc_par[0]);
820 break;
821 case 'g': /* tab stops */
822 switch (gc_par[0]) {
823 case 1:
824 case 2: /* reset tab stops */
825 /* gc_reset_tabs(); */
826 break;
827 case 3: /* Clear every tabs */
828 {
829 for (i = 0; i <= vinfo.v_columns; i++)
830 gc_set_tab_stop(i, FALSE);
831 }
832 break;
833 case 0:
834 gc_set_tab_stop(gc_x, FALSE);
835 break;
836 }
837 break;
838 case 'm': /* Set attribute */
839 for (i = 0; i < gc_numpars; i++) {
840 switch (gc_par[i]) {
841 case 0:
842 gc_attr = ATTR_NONE;
843 gc_update_color(COLOR_BACKGROUND, FALSE);
844 gc_update_color(COLOR_FOREGROUND, TRUE );
845 break;
846 case 1:
847 gc_attr |= ATTR_BOLD;
848 break;
849 case 4:
850 gc_attr |= ATTR_UNDER;
851 break;
852 case 7:
853 gc_attr |= ATTR_REVERSE;
854 break;
855 case 22:
856 gc_attr &= ~ATTR_BOLD;
857 break;
858 case 24:
859 gc_attr &= ~ATTR_UNDER;
860 break;
861 case 27:
862 gc_attr &= ~ATTR_REVERSE;
863 break;
864 case 5:
865 case 25: /* blink/no blink */
866 break;
867 default:
868 if (gc_par[i] >= 30 && gc_par[i] <= 37)
869 gc_update_color(gc_par[i] - 30, TRUE);
870 if (gc_par[i] >= 40 && gc_par[i] <= 47)
871 gc_update_color(gc_par[i] - 40, FALSE);
872 break;
873 }
874 }
875 break;
876 case 'r': /* Set scroll region */
877 gc_x = gc_y = 0;
878 /* ensure top < bottom, and both within limits */
879 if ((gc_numpars > 0) && (gc_par[0] < vinfo.v_rows)) {
880 gc_scrreg_top = gc_par[0] ? gc_par[0] - 1 : 0;
881 } else {
882 gc_scrreg_top = 0;
883 }
884 if ((gc_numpars > 1) && (gc_par[1] <= vinfo.v_rows) && (gc_par[1] > gc_par[0])) {
885 gc_scrreg_bottom = gc_par[1];
886 if (gc_scrreg_bottom > vinfo.v_rows)
887 gc_scrreg_bottom = vinfo.v_rows;
888 } else {
889 gc_scrreg_bottom = vinfo.v_rows;
890 }
891 if (gc_relative_origin)
892 gc_y = gc_scrreg_top;
893 break;
894 }
895
896 }
897
898 static void
899 gc_putc_normal(unsigned char ch)
900 {
901 switch (ch) {
902 case '\a': /* Beep */
903 break;
904 case 127: /* Delete */
905 case '\b': /* Backspace */
906 if (gc_hanging_cursor) {
907 gc_hanging_cursor = 0;
908 } else
909 if (gc_x > 0) {
910 gc_x--;
911 }
912 break;
913 case '\t': /* Tab */
914 if (gc_buffer_tab_stops) while (gc_x < vinfo.v_columns && !gc_is_tab_stop(++gc_x));
915
916 if (gc_x >= vinfo.v_columns)
917 gc_x = vinfo.v_columns-1;
918 break;
919 case 0x0b:
920 case 0x0c:
921 case '\n': /* Line feed */
922 if (gc_y >= gc_scrreg_bottom -1 ) {
923 gc_scroll_up(1, gc_scrreg_top, gc_scrreg_bottom);
924 gc_y = gc_scrreg_bottom - 1;
925 } else {
926 gc_y++;
927 }
928 break;
929 case '\r': /* Carriage return */
930 gc_x = 0;
931 gc_hanging_cursor = 0;
932 break;
933 case 0x0e: /* Select G1 charset (Control-N) */
934 gc_charset_select = 1;
935 break;
936 case 0x0f: /* Select G0 charset (Control-O) */
937 gc_charset_select = 0;
938 break;
939 case 0x18 : /* CAN : cancel */
940 case 0x1A : /* like cancel */
941 /* well, i do nothing here, may be later */
942 break;
943 case '\033': /* Escape */
944 gc_vt100state = ESesc;
945 gc_hanging_cursor = 0;
946 break;
947 default:
948 if (ch >= ' ') {
949 if (gc_hanging_cursor) {
950 gc_x = 0;
951 if (gc_y >= gc_scrreg_bottom -1 ) {
952 gc_scroll_up(1, gc_scrreg_top, gc_scrreg_bottom);
953 gc_y = gc_scrreg_bottom - 1;
954 } else {
955 gc_y++;
956 }
957 gc_hanging_cursor = 0;
958 }
959 gc_paint_char(gc_x, gc_y, (ch >= 0x60 && ch <= 0x7f) ? ch + gc_charset[gc_charset_select]
960 : ch, gc_attr);
961 if (gc_x == vinfo.v_columns - 1) {
962 gc_hanging_cursor = gc_wrap_mode;
963 } else {
964 gc_x++;
965 }
966 }
967 break;
968 }
969
970 }
971
972 static void
973 gc_putc_square(unsigned char ch)
974 {
975 int i;
976
977 for (i = 0; i < MAXPARS; i++) {
978 gc_par[i] = 0;
979 }
980
981 gc_numpars = 0;
982 gc_vt100state = ESgetpars;
983
984 gc_putc_getpars(ch);
985
986 }
987
988 static void
989 gc_reset_screen(void)
990 {
991 gc_reset_vt100();
992 gc_x = gc_y = 0;
993 }
994
995 static void
996 gc_reset_tabs(void)
997 {
998 unsigned int i;
999
1000 if (!gc_buffer_tab_stops) return;
1001
1002 for (i = 0; i < vinfo.v_columns; i++) {
1003 gc_buffer_tab_stops[i] = ((i % 8) == 0);
1004 }
1005
1006 }
1007
1008 static void
1009 gc_set_tab_stop(unsigned int column, boolean_t enabled)
1010 {
1011 if (gc_buffer_tab_stops && (column < vinfo.v_columns)) {
1012 gc_buffer_tab_stops[column] = enabled;
1013 }
1014 }
1015
1016 static boolean_t gc_is_tab_stop(unsigned int column)
1017 {
1018 if (gc_buffer_tab_stops == NULL)
1019 return ((column % 8) == 0);
1020 if (column < vinfo.v_columns)
1021 return gc_buffer_tab_stops[column];
1022 else
1023 return FALSE;
1024 }
1025
1026 static void
1027 gc_reset_vt100(void)
1028 {
1029 gc_reset_tabs();
1030 gc_scrreg_top = 0;
1031 gc_scrreg_bottom = vinfo.v_rows;
1032 gc_attr = ATTR_NONE;
1033 gc_charset[0] = gc_charset[1] = 0;
1034 gc_charset_select = 0;
1035 gc_wrap_mode = 1;
1036 gc_relative_origin = 0;
1037 gc_update_color(COLOR_BACKGROUND, FALSE);
1038 gc_update_color(COLOR_FOREGROUND, TRUE);
1039 }
1040
1041 static void
1042 gc_scroll_down(int num, unsigned int top, unsigned int bottom)
1043 {
1044 if (!gc_buffer_size) return;
1045
1046 if ( bottom <= gc_buffer_rows )
1047 {
1048 unsigned char colorcodesave = gc_color_code;
1049 uint32_t column, row;
1050 uint32_t index, jump;
1051
1052 jump = num * gc_buffer_columns;
1053
1054 for ( row = bottom - 1 ; row >= top + num ; row-- )
1055 {
1056 index = row * gc_buffer_columns;
1057
1058 for ( column = 0 ; column < gc_buffer_columns ; index++, column++ )
1059 {
1060 if ( gc_buffer_attributes[index] != gc_buffer_attributes[index - jump] ||
1061 gc_buffer_characters[index] != gc_buffer_characters[index - jump] ||
1062 gc_buffer_colorcodes[index] != gc_buffer_colorcodes[index - jump] )
1063 {
1064 if ( gc_color_code != gc_buffer_colorcodes[index - jump] )
1065 {
1066 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes[index - jump], TRUE ), TRUE );
1067 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes[index - jump], FALSE), FALSE);
1068 }
1069
1070 if ( gc_buffer_colorcodes[index] != gc_buffer_colorcodes[index - jump] )
1071 {
1072 gc_ops.paint_char( /* xx */ column,
1073 /* yy */ row,
1074 /* ch */ gc_buffer_characters[index - jump],
1075 /* attrs */ gc_buffer_attributes[index - jump],
1076 /* ch_previous */ 0,
1077 /* attrs_previous */ 0 );
1078 }
1079 else
1080 {
1081 gc_ops.paint_char( /* xx */ column,
1082 /* yy */ row,
1083 /* ch */ gc_buffer_characters[index - jump],
1084 /* attrs */ gc_buffer_attributes[index - jump],
1085 /* ch_previous */ gc_buffer_characters[index],
1086 /* attrs_previous */ gc_buffer_attributes[index] );
1087 }
1088
1089 gc_buffer_attributes[index] = gc_buffer_attributes[index - jump];
1090 gc_buffer_characters[index] = gc_buffer_characters[index - jump];
1091 gc_buffer_colorcodes[index] = gc_buffer_colorcodes[index - jump];
1092 }
1093 }
1094 }
1095
1096 if ( colorcodesave != gc_color_code )
1097 {
1098 gc_update_color(COLOR_CODE_GET(colorcodesave, TRUE ), TRUE );
1099 gc_update_color(COLOR_CODE_GET(colorcodesave, FALSE), FALSE);
1100 }
1101
1102 /* Now set the freed up lines to the background colour */
1103
1104 for ( row = top ; row < top + num ; row++ )
1105 {
1106 index = row * gc_buffer_columns;
1107
1108 for ( column = 0 ; column < gc_buffer_columns ; index++, column++ )
1109 {
1110 if ( gc_buffer_attributes[index] != ATTR_NONE ||
1111 gc_buffer_characters[index] != ' ' ||
1112 gc_buffer_colorcodes[index] != gc_color_code )
1113 {
1114 if ( gc_buffer_colorcodes[index] != gc_color_code )
1115 {
1116 gc_ops.paint_char( /* xx */ column,
1117 /* yy */ row,
1118 /* ch */ ' ',
1119 /* attrs */ ATTR_NONE,
1120 /* ch_previous */ 0,
1121 /* attrs_previous */ 0 );
1122 }
1123 else
1124 {
1125 gc_ops.paint_char( /* xx */ column,
1126 /* yy */ row,
1127 /* ch */ ' ',
1128 /* attrs */ ATTR_NONE,
1129 /* ch_previous */ gc_buffer_characters[index],
1130 /* attrs_previous */ gc_buffer_attributes[index] );
1131 }
1132
1133 gc_buffer_attributes[index] = ATTR_NONE;
1134 gc_buffer_characters[index] = ' ';
1135 gc_buffer_colorcodes[index] = gc_color_code;
1136 }
1137 }
1138 }
1139 }
1140 else
1141 {
1142 gc_ops.scroll_down(num, top, bottom);
1143
1144 /* Now set the freed up lines to the background colour */
1145
1146 gc_clear_screen(vinfo.v_columns - 1, top + num - 1, top, bottom, 1);
1147 }
1148 }
1149
1150 static void
1151 gc_scroll_up(int num, unsigned int top, unsigned int bottom)
1152 {
1153 if (!gc_buffer_size) return;
1154
1155 if ( bottom <= gc_buffer_rows )
1156 {
1157 unsigned char colorcodesave = gc_color_code;
1158 uint32_t column, row;
1159 uint32_t index, jump;
1160
1161 jump = num * gc_buffer_columns;
1162
1163 for ( row = top ; row < bottom - num ; row++ )
1164 {
1165 index = row * gc_buffer_columns;
1166
1167 for ( column = 0 ; column < gc_buffer_columns ; index++, column++ )
1168 {
1169 if ( gc_buffer_attributes[index] != gc_buffer_attributes[index + jump] ||
1170 gc_buffer_characters[index] != gc_buffer_characters[index + jump] ||
1171 gc_buffer_colorcodes[index] != gc_buffer_colorcodes[index + jump] )
1172 {
1173 if ( gc_color_code != gc_buffer_colorcodes[index + jump] )
1174 {
1175 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes[index + jump], TRUE ), TRUE );
1176 gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes[index + jump], FALSE), FALSE);
1177 }
1178
1179 if ( gc_buffer_colorcodes[index] != gc_buffer_colorcodes[index + jump] )
1180 {
1181 gc_ops.paint_char( /* xx */ column,
1182 /* yy */ row,
1183 /* ch */ gc_buffer_characters[index + jump],
1184 /* attrs */ gc_buffer_attributes[index + jump],
1185 /* ch_previous */ 0,
1186 /* attrs_previous */ 0 );
1187 }
1188 else
1189 {
1190 gc_ops.paint_char( /* xx */ column,
1191 /* yy */ row,
1192 /* ch */ gc_buffer_characters[index + jump],
1193 /* attrs */ gc_buffer_attributes[index + jump],
1194 /* ch_previous */ gc_buffer_characters[index],
1195 /* attrs_previous */ gc_buffer_attributes[index] );
1196 }
1197
1198 gc_buffer_attributes[index] = gc_buffer_attributes[index + jump];
1199 gc_buffer_characters[index] = gc_buffer_characters[index + jump];
1200 gc_buffer_colorcodes[index] = gc_buffer_colorcodes[index + jump];
1201 }
1202 }
1203 }
1204
1205 if ( colorcodesave != gc_color_code )
1206 {
1207 gc_update_color(COLOR_CODE_GET(colorcodesave, TRUE ), TRUE );
1208 gc_update_color(COLOR_CODE_GET(colorcodesave, FALSE), FALSE);
1209 }
1210
1211 /* Now set the freed up lines to the background colour */
1212
1213 for ( row = bottom - num ; row < bottom ; row++ )
1214 {
1215 index = row * gc_buffer_columns;
1216
1217 for ( column = 0 ; column < gc_buffer_columns ; index++, column++ )
1218 {
1219 if ( gc_buffer_attributes[index] != ATTR_NONE ||
1220 gc_buffer_characters[index] != ' ' ||
1221 gc_buffer_colorcodes[index] != gc_color_code )
1222 {
1223 if ( gc_buffer_colorcodes[index] != gc_color_code )
1224 {
1225 gc_ops.paint_char( /* xx */ column,
1226 /* yy */ row,
1227 /* ch */ ' ',
1228 /* attrs */ ATTR_NONE,
1229 /* ch_previous */ 0,
1230 /* attrs_previous */ 0 );
1231 }
1232 else
1233 {
1234 gc_ops.paint_char( /* xx */ column,
1235 /* yy */ row,
1236 /* ch */ ' ',
1237 /* attrs */ ATTR_NONE,
1238 /* ch_previous */ gc_buffer_characters[index],
1239 /* attrs_previous */ gc_buffer_attributes[index] );
1240 }
1241
1242 gc_buffer_attributes[index] = ATTR_NONE;
1243 gc_buffer_characters[index] = ' ';
1244 gc_buffer_colorcodes[index] = gc_color_code;
1245 }
1246 }
1247 }
1248 }
1249 else
1250 {
1251 gc_ops.scroll_up(num, top, bottom);
1252
1253 /* Now set the freed up lines to the background colour */
1254
1255 gc_clear_screen(0, bottom - num, top, bottom, 0);
1256 }
1257 }
1258
1259 static void
1260 gc_show_cursor(unsigned int xx, unsigned int yy)
1261 {
1262 if ( xx < gc_buffer_columns && yy < gc_buffer_rows )
1263 {
1264 uint32_t index = (yy * gc_buffer_columns) + xx;
1265 unsigned char attribute = gc_buffer_attributes[index];
1266 unsigned char character = gc_buffer_characters[index];
1267 unsigned char colorcode = gc_buffer_colorcodes[index];
1268 unsigned char colorcodesave = gc_color_code;
1269
1270 gc_update_color(COLOR_CODE_GET(colorcode, FALSE), TRUE );
1271 gc_update_color(COLOR_CODE_GET(colorcode, TRUE ), FALSE);
1272
1273 gc_ops.paint_char(xx, yy, character, attribute, 0, 0);
1274
1275 gc_update_color(COLOR_CODE_GET(colorcodesave, TRUE ), TRUE );
1276 gc_update_color(COLOR_CODE_GET(colorcodesave, FALSE), FALSE);
1277 }
1278 else
1279 {
1280 gc_ops.show_cursor(xx, yy);
1281 }
1282 }
1283
1284 static void
1285 gc_update_color(int color, boolean_t fore)
1286 {
1287 assert(gc_ops.update_color);
1288
1289 gc_color_code = COLOR_CODE_SET(gc_color_code, color, fore);
1290 gc_ops.update_color(color, fore);
1291 }
1292
1293 void
1294 vcputc(__unused int l, __unused int u, int c)
1295 {
1296 if ( gc_initialized && gc_enabled )
1297 {
1298 spl_t s;
1299
1300 s = splhigh();
1301 #if defined(__i386__) || defined(__x86_64__)
1302 x86_filter_TLB_coherency_interrupts(TRUE);
1303 #endif
1304 VCPUTC_LOCK_LOCK();
1305 if ( gc_enabled )
1306 {
1307 gc_hide_cursor(gc_x, gc_y);
1308 gc_putchar(c);
1309 gc_show_cursor(gc_x, gc_y);
1310 }
1311 VCPUTC_LOCK_UNLOCK();
1312 #if defined(__i386__) || defined(__x86_64__)
1313 x86_filter_TLB_coherency_interrupts(FALSE);
1314 #endif
1315 splx(s);
1316 }
1317 }
1318
1319 /*
1320 * Video Console (Back-End)
1321 * ------------------------
1322 */
1323
1324 /*
1325 * For the color support (Michel Pollet)
1326 */
1327 static unsigned char vc_color_index_table[33] =
1328 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1329 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 2 };
1330
1331 static uint32_t vc_colors[8][4] = {
1332 { 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000 }, /* black */
1333 { 0x23232323, 0x7C007C00, 0x00FF0000, 0x3FF00000 }, /* red */
1334 { 0xb9b9b9b9, 0x03e003e0, 0x0000FF00, 0x000FFC00 }, /* green */
1335 { 0x05050505, 0x7FE07FE0, 0x00FFFF00, 0x3FFFFC00 }, /* yellow */
1336 { 0xd2d2d2d2, 0x001f001f, 0x000000FF, 0x000003FF }, /* blue */
1337 // { 0x80808080, 0x31933193, 0x00666699, 0x00000000 }, /* blue */
1338 { 0x18181818, 0x7C1F7C1F, 0x00FF00FF, 0x3FF003FF }, /* magenta */
1339 { 0xb4b4b4b4, 0x03FF03FF, 0x0000FFFF, 0x000FFFFF }, /* cyan */
1340 { 0x00000000, 0x7FFF7FFF, 0x00FFFFFF, 0x3FFFFFFF } /* white */
1341 };
1342
1343 static uint32_t vc_color_fore = 0;
1344 static uint32_t vc_color_back = 0;
1345
1346 /*
1347 * New Rendering code from Michel Pollet
1348 */
1349
1350 /* Rendered Font Buffer */
1351 static unsigned char *vc_rendered_font = NULL;
1352
1353 /* Rendered Font Size */
1354 static uint32_t vc_rendered_font_size = 0;
1355
1356 /* Size of a character in the table (bytes) */
1357 static int vc_rendered_char_size = 0;
1358
1359 #define REN_MAX_DEPTH 32
1360 static unsigned char vc_rendered_char[ISO_CHAR_HEIGHT * ((REN_MAX_DEPTH / 8) * ISO_CHAR_WIDTH)];
1361
1362 #if !CONFIG_EMBEDDED
1363 static void
1364 internal_set_progressmeter(int new_value);
1365 static void
1366 internal_enable_progressmeter(int new_value);
1367
1368 enum
1369 {
1370 kProgressMeterOff = FALSE,
1371 kProgressMeterUser = TRUE,
1372 kProgressMeterKernel = 3,
1373 };
1374 enum
1375 {
1376 kProgressMeterMax = 1024,
1377 kProgressMeterEnd = 512,
1378 };
1379
1380 #endif /* !CONFIG_EMBEDDED */
1381
1382 static boolean_t vc_progress_white =
1383 #ifdef CONFIG_VC_PROGRESS_WHITE
1384 TRUE;
1385 #else /* !CONFIG_VC_PROGRESS_WHITE */
1386 FALSE;
1387 #endif /* !CONFIG_VC_PROGRESS_WHITE */
1388
1389 static int vc_acquire_delay = kProgressAcquireDelay;
1390
1391 static void
1392 vc_clear_screen(unsigned int xx, unsigned int yy, unsigned int scrreg_top,
1393 unsigned int scrreg_bottom, int which)
1394 {
1395 uint32_t *p, *endp, *row;
1396 int linelongs, col;
1397 int rowline, rowlongs;
1398
1399 if(!vinfo.v_depth)
1400 return;
1401
1402 linelongs = vinfo.v_rowbytes * (ISO_CHAR_HEIGHT >> 2);
1403 rowline = vinfo.v_rowscanbytes >> 2;
1404 rowlongs = vinfo.v_rowbytes >> 2;
1405
1406 p = (uint32_t*) vinfo.v_baseaddr;
1407 endp = (uint32_t*) vinfo.v_baseaddr;
1408
1409 switch (which) {
1410 case 0: /* To end of screen */
1411 gc_clear_line(xx, yy, 0);
1412 if (yy < scrreg_bottom - 1) {
1413 p += (yy + 1) * linelongs;
1414 endp += scrreg_bottom * linelongs;
1415 }
1416 break;
1417 case 1: /* To start of screen */
1418 gc_clear_line(xx, yy, 1);
1419 if (yy > scrreg_top) {
1420 p += scrreg_top * linelongs;
1421 endp += yy * linelongs;
1422 }
1423 break;
1424 case 2: /* Whole screen */
1425 p += scrreg_top * linelongs;
1426 if (scrreg_bottom == vinfo.v_rows) {
1427 endp += rowlongs * vinfo.v_height;
1428 } else {
1429 endp += scrreg_bottom * linelongs;
1430 }
1431 break;
1432 }
1433
1434 for (row = p ; row < endp ; row += rowlongs) {
1435 for (col = 0; col < rowline; col++)
1436 *(row+col) = vc_color_back;
1437 }
1438 }
1439
1440 static void
1441 vc_render_char(unsigned char ch, unsigned char *renderptr, short newdepth)
1442 {
1443 union {
1444 unsigned char *charptr;
1445 unsigned short *shortptr;
1446 uint32_t *longptr;
1447 } current; /* current place in rendered font, multiple types. */
1448 unsigned char *theChar; /* current char in iso_font */
1449 int line;
1450
1451 current.charptr = renderptr;
1452 theChar = iso_font + (ch * ISO_CHAR_HEIGHT);
1453
1454 for (line = 0; line < ISO_CHAR_HEIGHT; line++) {
1455 unsigned char mask = 1;
1456 do {
1457 switch (newdepth) {
1458 case 8:
1459 *current.charptr++ = (*theChar & mask) ? 0xFF : 0;
1460 break;
1461 case 16:
1462 *current.shortptr++ = (*theChar & mask) ? 0xFFFF : 0;
1463 break;
1464
1465 case 30:
1466 case 32:
1467 *current.longptr++ = (*theChar & mask) ? 0xFFFFFFFF : 0;
1468 break;
1469 }
1470 mask <<= 1;
1471 } while (mask); /* while the single bit drops to the right */
1472 theChar++;
1473 }
1474 }
1475
1476 static void
1477 vc_paint_char_8(unsigned int xx, unsigned int yy, unsigned char ch, int attrs,
1478 __unused unsigned char ch_previous, __unused int attrs_previous)
1479 {
1480 uint32_t *theChar;
1481 uint32_t *where;
1482 int i;
1483
1484 if (vc_rendered_font) {
1485 theChar = (uint32_t*)(vc_rendered_font + (ch * vc_rendered_char_size));
1486 } else {
1487 vc_render_char(ch, vc_rendered_char, 8);
1488 theChar = (uint32_t*)(vc_rendered_char);
1489 }
1490 where = (uint32_t*)(vinfo.v_baseaddr +
1491 (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) +
1492 (xx * ISO_CHAR_WIDTH));
1493
1494 if (!attrs) for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* No attr? FLY !*/
1495 uint32_t *store = where;
1496 int x;
1497 for (x = 0; x < 2; x++) {
1498 uint32_t val = *theChar++;
1499 val = (vc_color_back & ~val) | (vc_color_fore & val);
1500 *store++ = val;
1501 }
1502
1503 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
1504 } else for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* a little slower */
1505 uint32_t *store = where, lastpixel = 0;
1506 int x;
1507 for (x = 0 ; x < 2; x++) {
1508 uint32_t val = *theChar++, save = val;
1509 if (attrs & ATTR_BOLD) { /* bold support */
1510 if (lastpixel && !(save & 0xFF000000))
1511 val |= 0xff000000;
1512 if ((save & 0xFFFF0000) == 0xFF000000)
1513 val |= 0x00FF0000;
1514 if ((save & 0x00FFFF00) == 0x00FF0000)
1515 val |= 0x0000FF00;
1516 if ((save & 0x0000FFFF) == 0x0000FF00)
1517 val |= 0x000000FF;
1518 }
1519 if (attrs & ATTR_REVERSE) val = ~val;
1520 if (attrs & ATTR_UNDER && i == ISO_CHAR_HEIGHT-1) val = ~val;
1521
1522 val = (vc_color_back & ~val) | (vc_color_fore & val);
1523 *store++ = val;
1524 lastpixel = save & 0xff;
1525 }
1526
1527 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
1528 }
1529
1530 }
1531
1532 static void
1533 vc_paint_char_16(unsigned int xx, unsigned int yy, unsigned char ch, int attrs,
1534 __unused unsigned char ch_previous,
1535 __unused int attrs_previous)
1536 {
1537 uint32_t *theChar;
1538 uint32_t *where;
1539 int i;
1540
1541 if (vc_rendered_font) {
1542 theChar = (uint32_t*)(vc_rendered_font + (ch * vc_rendered_char_size));
1543 } else {
1544 vc_render_char(ch, vc_rendered_char, 16);
1545 theChar = (uint32_t*)(vc_rendered_char);
1546 }
1547 where = (uint32_t*)(vinfo.v_baseaddr +
1548 (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) +
1549 (xx * ISO_CHAR_WIDTH * 2));
1550
1551 if (!attrs) for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* No attrs ? FLY ! */
1552 uint32_t *store = where;
1553 int x;
1554 for (x = 0; x < 4; x++) {
1555 uint32_t val = *theChar++;
1556 val = (vc_color_back & ~val) | (vc_color_fore & val);
1557 *store++ = val;
1558 }
1559
1560 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
1561 } else for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* a little bit slower */
1562 uint32_t *store = where, lastpixel = 0;
1563 int x;
1564 for (x = 0 ; x < 4; x++) {
1565 uint32_t val = *theChar++, save = val;
1566 if (attrs & ATTR_BOLD) { /* bold support */
1567 if (save == 0xFFFF0000) val |= 0xFFFF;
1568 else if (lastpixel && !(save & 0xFFFF0000))
1569 val |= 0xFFFF0000;
1570 }
1571 if (attrs & ATTR_REVERSE) val = ~val;
1572 if (attrs & ATTR_UNDER && i == ISO_CHAR_HEIGHT-1) val = ~val;
1573
1574 val = (vc_color_back & ~val) | (vc_color_fore & val);
1575
1576 *store++ = val;
1577 lastpixel = save & 0x7fff;
1578 }
1579
1580 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
1581 }
1582
1583 }
1584
1585 static void
1586 vc_paint_char_32(unsigned int xx, unsigned int yy, unsigned char ch, int attrs,
1587 unsigned char ch_previous, int attrs_previous)
1588 {
1589 uint32_t *theChar;
1590 uint32_t *theCharPrevious;
1591 uint32_t *where;
1592 int i;
1593
1594 if (vc_rendered_font) {
1595 theChar = (uint32_t*)(vc_rendered_font + (ch * vc_rendered_char_size));
1596 theCharPrevious = (uint32_t*)(vc_rendered_font + (ch_previous * vc_rendered_char_size));
1597 } else {
1598 vc_render_char(ch, vc_rendered_char, 32);
1599 theChar = (uint32_t*)(vc_rendered_char);
1600 theCharPrevious = NULL;
1601 }
1602 if (!ch_previous) {
1603 theCharPrevious = NULL;
1604 }
1605 if (attrs_previous) {
1606 theCharPrevious = NULL;
1607 }
1608 where = (uint32_t*)(vinfo.v_baseaddr +
1609 (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) +
1610 (xx * ISO_CHAR_WIDTH * 4));
1611
1612 if (!attrs) for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* No attrs ? FLY ! */
1613 uint32_t *store = where;
1614 int x;
1615 for (x = 0; x < 8; x++) {
1616 uint32_t val = *theChar++;
1617 if (theCharPrevious == NULL || val != *theCharPrevious++ ) {
1618 val = (vc_color_back & ~val) | (vc_color_fore & val);
1619 *store++ = val;
1620 } else {
1621 store++;
1622 }
1623 }
1624
1625 where = (uint32_t *)(((unsigned char*)where)+vinfo.v_rowbytes);
1626 } else for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* a little slower */
1627 uint32_t *store = where, lastpixel = 0;
1628 int x;
1629 for (x = 0 ; x < 8; x++) {
1630 uint32_t val = *theChar++, save = val;
1631 if (attrs & ATTR_BOLD) { /* bold support */
1632 if (lastpixel && !save)
1633 val = 0xFFFFFFFF;
1634 }
1635 if (attrs & ATTR_REVERSE) val = ~val;
1636 if (attrs & ATTR_UNDER && i == ISO_CHAR_HEIGHT-1) val = ~val;
1637
1638 val = (vc_color_back & ~val) | (vc_color_fore & val);
1639 *store++ = val;
1640 lastpixel = save;
1641 }
1642
1643 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
1644 }
1645
1646 }
1647
1648 static void
1649 vc_paint_char(unsigned int xx, unsigned int yy, unsigned char ch, int attrs,
1650 unsigned char ch_previous, int attrs_previous)
1651 {
1652 if(!vinfo.v_depth)
1653 return;
1654
1655 switch(vinfo.v_depth) {
1656 case 8:
1657 vc_paint_char_8(xx, yy, ch, attrs, ch_previous, attrs_previous);
1658 break;
1659 case 16:
1660 vc_paint_char_16(xx, yy, ch, attrs, ch_previous,
1661 attrs_previous);
1662 break;
1663 case 30:
1664 case 32:
1665 vc_paint_char_32(xx, yy, ch, attrs, ch_previous,
1666 attrs_previous);
1667 break;
1668 }
1669 }
1670
1671 static void
1672 vc_render_font(short newdepth)
1673 {
1674 static short olddepth = 0;
1675
1676 int charindex; /* index in ISO font */
1677 unsigned char *rendered_font;
1678 unsigned int rendered_font_size;
1679 int rendered_char_size;
1680 spl_t s;
1681
1682 if (vm_initialized == FALSE) {
1683 return; /* nothing to do */
1684 }
1685 if (olddepth == newdepth && vc_rendered_font) {
1686 return; /* nothing to do */
1687 }
1688
1689 s = splhigh();
1690 VCPUTC_LOCK_LOCK();
1691
1692 rendered_font = vc_rendered_font;
1693 rendered_font_size = vc_rendered_font_size;
1694 rendered_char_size = vc_rendered_char_size;
1695
1696 vc_rendered_font = NULL;
1697 vc_rendered_font_size = 0;
1698 vc_rendered_char_size = 0;
1699
1700 VCPUTC_LOCK_UNLOCK();
1701 splx(s);
1702
1703 if (rendered_font) {
1704 kfree(rendered_font, rendered_font_size);
1705 rendered_font = NULL;
1706 }
1707
1708 if (newdepth) {
1709 rendered_char_size = ISO_CHAR_HEIGHT * (((newdepth + 7) / 8) * ISO_CHAR_WIDTH);
1710 rendered_font_size = (ISO_CHAR_MAX-ISO_CHAR_MIN+1) * rendered_char_size;
1711 rendered_font = (unsigned char *) kalloc(rendered_font_size);
1712 }
1713
1714 if (rendered_font == NULL) {
1715 return;
1716 }
1717
1718 for (charindex = ISO_CHAR_MIN; charindex <= ISO_CHAR_MAX; charindex++) {
1719 vc_render_char(charindex, rendered_font + (charindex * rendered_char_size), newdepth);
1720 }
1721
1722 olddepth = newdepth;
1723
1724 s = splhigh();
1725 VCPUTC_LOCK_LOCK();
1726
1727 vc_rendered_font = rendered_font;
1728 vc_rendered_font_size = rendered_font_size;
1729 vc_rendered_char_size = rendered_char_size;
1730
1731 VCPUTC_LOCK_UNLOCK();
1732 splx(s);
1733 }
1734
1735 static void
1736 vc_enable(boolean_t enable)
1737 {
1738 vc_render_font(enable ? vinfo.v_depth : 0);
1739 }
1740
1741 static void
1742 vc_reverse_cursor(unsigned int xx, unsigned int yy)
1743 {
1744 uint32_t *where;
1745 int line, col;
1746
1747 if(!vinfo.v_depth)
1748 return;
1749
1750 where = (uint32_t*)(vinfo.v_baseaddr +
1751 (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) +
1752 (xx /** ISO_CHAR_WIDTH*/ * vinfo.v_depth));
1753 for (line = 0; line < ISO_CHAR_HEIGHT; line++) {
1754 switch (vinfo.v_depth) {
1755 case 8:
1756 where[0] = ~where[0];
1757 where[1] = ~where[1];
1758 break;
1759 case 16:
1760 for (col = 0; col < 4; col++)
1761 where[col] = ~where[col];
1762 break;
1763 case 32:
1764 for (col = 0; col < 8; col++)
1765 where[col] = ~where[col];
1766 break;
1767 }
1768 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
1769 }
1770 }
1771
1772 static void
1773 vc_scroll_down(int num, unsigned int scrreg_top, unsigned int scrreg_bottom)
1774 {
1775 uint32_t *from, *to, linelongs, i, line, rowline, rowscanline;
1776
1777 if(!vinfo.v_depth)
1778 return;
1779
1780 linelongs = vinfo.v_rowbytes * (ISO_CHAR_HEIGHT >> 2);
1781 rowline = vinfo.v_rowbytes >> 2;
1782 rowscanline = vinfo.v_rowscanbytes >> 2;
1783
1784 to = (uint32_t *) vinfo.v_baseaddr + (linelongs * scrreg_bottom)
1785 - (rowline - rowscanline);
1786 from = to - (linelongs * num); /* handle multiple line scroll (Michel Pollet) */
1787
1788 i = (scrreg_bottom - scrreg_top) - num;
1789
1790 while (i-- > 0) {
1791 for (line = 0; line < ISO_CHAR_HEIGHT; line++) {
1792 /*
1793 * Only copy what is displayed
1794 */
1795 video_scroll_down(from,
1796 (from-(vinfo.v_rowscanbytes >> 2)),
1797 to);
1798
1799 from -= rowline;
1800 to -= rowline;
1801 }
1802 }
1803 }
1804
1805 static void
1806 vc_scroll_up(int num, unsigned int scrreg_top, unsigned int scrreg_bottom)
1807 {
1808 uint32_t *from, *to, linelongs, i, line, rowline, rowscanline;
1809
1810 if(!vinfo.v_depth)
1811 return;
1812
1813 linelongs = vinfo.v_rowbytes * (ISO_CHAR_HEIGHT >> 2);
1814 rowline = vinfo.v_rowbytes >> 2;
1815 rowscanline = vinfo.v_rowscanbytes >> 2;
1816
1817 to = (uint32_t *) vinfo.v_baseaddr + (scrreg_top * linelongs);
1818 from = to + (linelongs * num); /* handle multiple line scroll (Michel Pollet) */
1819
1820 i = (scrreg_bottom - scrreg_top) - num;
1821
1822 while (i-- > 0) {
1823 for (line = 0; line < ISO_CHAR_HEIGHT; line++) {
1824 /*
1825 * Only copy what is displayed
1826 */
1827 video_scroll_up(from,
1828 (from+(vinfo.v_rowscanbytes >> 2)),
1829 to);
1830
1831 from += rowline;
1832 to += rowline;
1833 }
1834 }
1835 }
1836
1837 static void
1838 vc_update_color(int color, boolean_t fore)
1839 {
1840 if (!vinfo.v_depth)
1841 return;
1842 if (fore) {
1843 vc_color_fore = vc_colors[color][vc_color_index_table[vinfo.v_depth]];
1844 } else {
1845 vc_color_back = vc_colors[color][vc_color_index_table[vinfo.v_depth]];
1846 }
1847 }
1848
1849 /*
1850 * Video Console (Back-End): Icon Control
1851 * --------------------------------------
1852 */
1853
1854 static vc_progress_element * vc_progress;
1855 enum { kMaxProgressData = 3 };
1856 static const unsigned char * vc_progress_data[kMaxProgressData];
1857 static const unsigned char * vc_progress_alpha;
1858 static boolean_t vc_progress_enable;
1859 static const unsigned char * vc_clut;
1860 static const unsigned char * vc_clut8;
1861 static unsigned char vc_revclut8[256];
1862 static uint32_t vc_progress_interval;
1863 static uint32_t vc_progress_count;
1864 static uint32_t vc_progress_angle;
1865 static uint64_t vc_progress_deadline;
1866 static thread_call_data_t vc_progress_call;
1867 static boolean_t vc_needsave;
1868 static void * vc_saveunder;
1869 static vm_size_t vc_saveunder_len;
1870 static int8_t vc_uiscale = 1;
1871 vc_progress_user_options vc_progress_options;
1872 vc_progress_user_options vc_user_options;
1873
1874 decl_simple_lock_data(,vc_progress_lock)
1875
1876 #if !CONFIG_EMBEDDED
1877 static int vc_progress_withmeter = 3;
1878 int vc_progressmeter_enable;
1879 static int vc_progressmeter_drawn;
1880 int vc_progressmeter_value;
1881 static uint32_t vc_progressmeter_count;
1882 static uint32_t vc_progress_meter_start;
1883 static uint32_t vc_progress_meter_end;
1884 static uint64_t vc_progressmeter_interval;
1885 static uint64_t vc_progressmeter_deadline;
1886 static thread_call_data_t vc_progressmeter_call;
1887 static void * vc_progressmeter_backbuffer;
1888 static boolean_t vc_progressmeter_hold;
1889 static uint32_t vc_progressmeter_diskspeed = 256;
1890
1891 #endif /* !CONFIG_EMBEDDED */
1892
1893 enum {
1894 kSave = 0x10,
1895 kDataIndexed = 0x20,
1896 kDataAlpha = 0x40,
1897 kDataBack = 0x80,
1898 kDataRotate = 0x03,
1899 };
1900
1901 static void vc_blit_rect(int x, int y, int bx,
1902 int width, int height,
1903 int sourceWidth, int sourceHeight,
1904 int sourceRow, int backRow,
1905 const unsigned char * dataPtr,
1906 void * backBuffer,
1907 unsigned int flags);
1908 static void vc_blit_rect_8(int x, int y, int bx,
1909 int width, int height,
1910 int sourceWidth, int sourceHeight,
1911 int sourceRow, int backRow,
1912 const unsigned char * dataPtr,
1913 unsigned char * backBuffer,
1914 unsigned int flags);
1915 static void vc_blit_rect_16(int x, int y, int bx,
1916 int width, int height,
1917 int sourceWidth, int sourceHeight,
1918 int sourceRow, int backRow,
1919 const unsigned char * dataPtr,
1920 unsigned short * backBuffer,
1921 unsigned int flags);
1922 static void vc_blit_rect_32(int x, int y, int bx,
1923 int width, int height,
1924 int sourceWidth, int sourceHeight,
1925 int sourceRow, int backRow,
1926 const unsigned char * dataPtr,
1927 unsigned int * backBuffer,
1928 unsigned int flags);
1929 static void vc_blit_rect_30(int x, int y, int bx,
1930 int width, int height,
1931 int sourceWidth, int sourceHeight,
1932 int sourceRow, int backRow,
1933 const unsigned char * dataPtr,
1934 unsigned int * backBuffer,
1935 unsigned int flags);
1936 static void vc_progress_task( void * arg0, void * arg );
1937 #if !CONFIG_EMBEDDED
1938 static void vc_progressmeter_task( void * arg0, void * arg );
1939 #endif /* !CONFIG_EMBEDDED */
1940
1941 static void vc_blit_rect(int x, int y, int bx,
1942 int width, int height,
1943 int sourceWidth, int sourceHeight,
1944 int sourceRow, int backRow,
1945 const unsigned char * dataPtr,
1946 void * backBuffer,
1947 unsigned int flags)
1948 {
1949 if (!vinfo.v_depth) return;
1950 if (((unsigned int)(x + width)) > vinfo.v_width) return;
1951 if (((unsigned int)(y + height)) > vinfo.v_height) return;
1952
1953 switch( vinfo.v_depth) {
1954 case 8:
1955 if( vc_clut8 == vc_clut)
1956 vc_blit_rect_8( x, y, bx, width, height, sourceWidth, sourceHeight, sourceRow, backRow, dataPtr, (unsigned char *) backBuffer, flags );
1957 break;
1958 case 16:
1959 vc_blit_rect_16( x, y, bx, width, height, sourceWidth, sourceHeight, sourceRow, backRow, dataPtr, (unsigned short *) backBuffer, flags );
1960 break;
1961 case 32:
1962 vc_blit_rect_32( x, y, bx, width, height, sourceWidth, sourceHeight, sourceRow, backRow, dataPtr, (unsigned int *) backBuffer, flags );
1963 break;
1964 case 30:
1965 vc_blit_rect_30( x, y, bx, width, height, sourceWidth, sourceHeight, sourceRow, backRow, dataPtr, (unsigned int *) backBuffer, flags );
1966 break;
1967 }
1968 }
1969
1970 static void
1971 vc_blit_rect_8(int x, int y, __unused int bx,
1972 int width, int height,
1973 int sourceWidth, int sourceHeight,
1974 int sourceRow, __unused int backRow,
1975 const unsigned char * dataPtr,
1976 __unused unsigned char * backBuffer,
1977 __unused unsigned int flags)
1978 {
1979 volatile unsigned short * dst;
1980 int line, col;
1981 unsigned int data = 0, out = 0;
1982 int sx, sy, a, b, c, d;
1983 int scale = 0x10000;
1984
1985 a = (sourceRow == 1) ? 0 : vc_rotate_matr[kDataRotate & flags][0][0] * scale;
1986 b = (sourceRow == 1) ? 0 : vc_rotate_matr[kDataRotate & flags][0][1] * scale;
1987 c = vc_rotate_matr[kDataRotate & flags][1][0] * scale;
1988 d = vc_rotate_matr[kDataRotate & flags][1][1] * scale;
1989
1990 sx = ((a + b) < 0) ? ((sourceWidth * scale) - 0x8000) : 0;
1991 sy = ((c + d) < 0) ? ((sourceHeight * scale) - 0x8000) : 0;
1992
1993 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr;
1994
1995 dst = (volatile unsigned short *) (vinfo.v_baseaddr +
1996 (y * vinfo.v_rowbytes) +
1997 (x * 4));
1998
1999 for( line = 0; line < height; line++)
2000 {
2001 for( col = 0; col < width; col++)
2002 {
2003 if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16)
2004 + sourceRow * (((sy + (col * c) + (line * d)) >> 16))];
2005 if (kDataAlpha & flags)
2006 out = vc_revclut8[data];
2007 else
2008 out = data;
2009 *(dst + col) = out;
2010 }
2011 dst = (volatile unsigned short *) (((volatile char*)dst) + vinfo.v_rowbytes);
2012 }
2013 }
2014
2015 /* For ARM, 16-bit is 565 (RGB); it is 1555 (XRGB) on other platforms */
2016
2017 #ifdef __arm__
2018 #define CLUT_MASK_R 0xf8
2019 #define CLUT_MASK_G 0xfc
2020 #define CLUT_MASK_B 0xf8
2021 #define CLUT_SHIFT_R << 8
2022 #define CLUT_SHIFT_G << 3
2023 #define CLUT_SHIFT_B >> 3
2024 #define MASK_R 0xf800
2025 #define MASK_G 0x07e0
2026 #define MASK_B 0x001f
2027 #define MASK_R_8 0x7f800
2028 #define MASK_G_8 0x01fe0
2029 #define MASK_B_8 0x000ff
2030 #else
2031 #define CLUT_MASK_R 0xf8
2032 #define CLUT_MASK_G 0xf8
2033 #define CLUT_MASK_B 0xf8
2034 #define CLUT_SHIFT_R << 7
2035 #define CLUT_SHIFT_G << 2
2036 #define CLUT_SHIFT_B >> 3
2037 #define MASK_R 0x7c00
2038 #define MASK_G 0x03e0
2039 #define MASK_B 0x001f
2040 #define MASK_R_8 0x3fc00
2041 #define MASK_G_8 0x01fe0
2042 #define MASK_B_8 0x000ff
2043 #endif
2044
2045 static void vc_blit_rect_16( int x, int y, int bx,
2046 int width, int height,
2047 int sourceWidth, int sourceHeight,
2048 int sourceRow, int backRow,
2049 const unsigned char * dataPtr,
2050 unsigned short * backPtr,
2051 unsigned int flags)
2052 {
2053 volatile unsigned short * dst;
2054 int line, col;
2055 unsigned int data = 0, out = 0, back = 0;
2056 int sx, sy, a, b, c, d;
2057 int scale = 0x10000;
2058
2059 a = (sourceRow == 1) ? 0 : vc_rotate_matr[kDataRotate & flags][0][0] * scale;
2060 b = (sourceRow == 1) ? 0 : vc_rotate_matr[kDataRotate & flags][0][1] * scale;
2061 c = vc_rotate_matr[kDataRotate & flags][1][0] * scale;
2062 d = vc_rotate_matr[kDataRotate & flags][1][1] * scale;
2063
2064 sx = ((a + b) < 0) ? ((sourceWidth * scale) - 0x8000) : 0;
2065 sy = ((c + d) < 0) ? ((sourceHeight * scale) - 0x8000) : 0;
2066
2067 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr;
2068
2069 if (backPtr)
2070 backPtr += bx;
2071 dst = (volatile unsigned short *) (vinfo.v_baseaddr +
2072 (y * vinfo.v_rowbytes) +
2073 (x * 2));
2074
2075 for( line = 0; line < height; line++)
2076 {
2077 for( col = 0; col < width; col++)
2078 {
2079 if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16)
2080 + sourceRow * (((sy + (col * c) + (line * d)) >> 16))];
2081 if (backPtr) {
2082 if (kSave & flags) {
2083 back = *(dst + col);
2084 *backPtr++ = back;
2085 } else
2086 back = *backPtr++;
2087 }
2088 if (kDataIndexed & flags) {
2089 out = ( (CLUT_MASK_R & (vc_clut[data*3 + 0])) CLUT_SHIFT_R)
2090 | ( (CLUT_MASK_G & (vc_clut[data*3 + 1])) CLUT_SHIFT_G)
2091 | ( (CLUT_MASK_B & (vc_clut[data*3 + 2])) CLUT_SHIFT_B);
2092 } else if (kDataAlpha & flags) {
2093 out = (((((back & MASK_R) * data) + MASK_R_8) >> 8) & MASK_R)
2094 | (((((back & MASK_G) * data) + MASK_G_8) >> 8) & MASK_G)
2095 | (((((back & MASK_B) * data) + MASK_B_8) >> 8) & MASK_B);
2096 if (vc_progress_white) out += (((0xff - data) & CLUT_MASK_R) CLUT_SHIFT_R)
2097 | (((0xff - data) & CLUT_MASK_G) CLUT_SHIFT_G)
2098 | (((0xff - data) & CLUT_MASK_B) CLUT_SHIFT_B);
2099 } else if (kDataBack & flags)
2100 out = back;
2101 else
2102 out = data;
2103 *(dst + col) = out;
2104 }
2105 dst = (volatile unsigned short *) (((volatile char*)dst) + vinfo.v_rowbytes);
2106 if (backPtr)
2107 backPtr += backRow - width;
2108 }
2109 }
2110
2111
2112 static void vc_blit_rect_32(int x, int y, int bx,
2113 int width, int height,
2114 int sourceWidth, int sourceHeight,
2115 int sourceRow, int backRow,
2116 const unsigned char * dataPtr,
2117 unsigned int * backPtr,
2118 unsigned int flags)
2119 {
2120 volatile unsigned int * dst;
2121 int line, col;
2122 unsigned int data = 0, out = 0, back = 0;
2123 int sx, sy, a, b, c, d;
2124 int scale = 0x10000;
2125
2126 a = (sourceRow == 1) ? 0 : vc_rotate_matr[kDataRotate & flags][0][0] * scale;
2127 b = (sourceRow == 1) ? 0 : vc_rotate_matr[kDataRotate & flags][0][1] * scale;
2128 c = vc_rotate_matr[kDataRotate & flags][1][0] * scale;
2129 d = vc_rotate_matr[kDataRotate & flags][1][1] * scale;
2130
2131 sx = ((a + b) < 0) ? ((sourceWidth * scale) - 0x8000) : 0;
2132 sy = ((c + d) < 0) ? ((sourceHeight * scale) - 0x8000) : 0;
2133
2134 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr;
2135
2136 if (backPtr)
2137 backPtr += bx;
2138 dst = (volatile unsigned int *) (vinfo.v_baseaddr +
2139 (y * vinfo.v_rowbytes) +
2140 (x * 4));
2141
2142 for( line = 0; line < height; line++)
2143 {
2144 for( col = 0; col < width; col++)
2145 {
2146 if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16)
2147 + sourceRow * (((sy + (col * c) + (line * d)) >> 16))];
2148 if (backPtr) {
2149 if (kSave & flags) {
2150 back = *(dst + col);
2151 *backPtr++ = back;
2152 } else
2153 back = *backPtr++;
2154 }
2155 if (kDataIndexed & flags) {
2156 out = (vc_clut[data*3 + 0] << 16)
2157 | (vc_clut[data*3 + 1] << 8)
2158 | (vc_clut[data*3 + 2]);
2159 } else if (kDataAlpha & flags) {
2160 out = (((((back & 0x00ff00ff) * data) + 0x00ff00ff) >> 8) & 0x00ff00ff)
2161 | (((((back & 0x0000ff00) * data) + 0x0000ff00) >> 8) & 0x0000ff00);
2162 if (vc_progress_white) out += ((0xff - data) << 16)
2163 | ((0xff - data) << 8)
2164 | (0xff - data);
2165 } else if (kDataBack & flags)
2166 out = back;
2167 else
2168 out = data;
2169 *(dst + col) = out;
2170 }
2171 dst = (volatile unsigned int *) (((volatile char*)dst) + vinfo.v_rowbytes);
2172 if (backPtr)
2173 backPtr += backRow - width;
2174 }
2175 }
2176
2177 static void vc_blit_rect_30(int x, int y, int bx,
2178 int width, int height,
2179 int sourceWidth, int sourceHeight,
2180 int sourceRow, int backRow,
2181 const unsigned char * dataPtr,
2182 unsigned int * backPtr,
2183 unsigned int flags)
2184 {
2185 volatile unsigned int * dst;
2186 int line, col;
2187 unsigned int data = 0, out = 0, back = 0;
2188 unsigned long long exp;
2189 int sx, sy, a, b, c, d;
2190 int scale = 0x10000;
2191
2192 a = (sourceRow == 1) ? 0 : vc_rotate_matr[kDataRotate & flags][0][0] * scale;
2193 b = (sourceRow == 1) ? 0 : vc_rotate_matr[kDataRotate & flags][0][1] * scale;
2194 c = vc_rotate_matr[kDataRotate & flags][1][0] * scale;
2195 d = vc_rotate_matr[kDataRotate & flags][1][1] * scale;
2196
2197 sx = ((a + b) < 0) ? ((sourceWidth * scale) - 0x8000) : 0;
2198 sy = ((c + d) < 0) ? ((sourceHeight * scale) - 0x8000) : 0;
2199
2200 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr;
2201
2202 if (backPtr)
2203 backPtr += bx;
2204 dst = (volatile unsigned int *) (vinfo.v_baseaddr +
2205 (y * vinfo.v_rowbytes) +
2206 (x * 4));
2207
2208 for( line = 0; line < height; line++)
2209 {
2210 for( col = 0; col < width; col++)
2211 {
2212 if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16)
2213 + sourceRow * (((sy + (col * c) + (line * d)) >> 16))];
2214 if (backPtr) {
2215 if (kSave & flags) {
2216 back = *(dst + col);
2217 *backPtr++ = back;
2218 } else
2219 back = *backPtr++;
2220 }
2221 if (kDataIndexed & flags) {
2222 out = (vc_clut[data*3 + 0] << 22)
2223 | (vc_clut[data*3 + 1] << 12)
2224 | (vc_clut[data*3 + 2] << 2);
2225 } else if (kDataAlpha & flags) {
2226 exp = back;
2227 exp = (((((exp & 0x3FF003FF) * data) + 0x0FF000FF) >> 8) & 0x3FF003FF)
2228 | (((((exp & 0x000FFC00) * data) + 0x0003FC00) >> 8) & 0x000FFC00);
2229 out = (unsigned int)exp;
2230 if (vc_progress_white) out += ((0xFF - data) << 22)
2231 | ((0xFF - data) << 12)
2232 | ((0xFF - data) << 2);
2233 } else if (kDataBack & flags)
2234 out = back;
2235 else
2236 out = data;
2237 *(dst + col) = out;
2238 }
2239 dst = (volatile unsigned int *) (((volatile char*)dst) + vinfo.v_rowbytes);
2240 if (backPtr)
2241 backPtr += backRow - width;
2242 }
2243 }
2244
2245 static void vc_clean_boot_graphics(void)
2246 {
2247 #if !CONFIG_EMBEDDED
2248 // clean up possible FDE login graphics
2249 vc_progress_set(FALSE, 0);
2250 const unsigned char *
2251 color = (typeof(color))(uintptr_t)(vc_progress_white ? 0x00000000 : 0xBFBFBFBF);
2252 vc_blit_rect(0, 0, 0, vinfo.v_width, vinfo.v_height, vinfo.v_width, vinfo.v_height, 0, 0, color, NULL, 0);
2253 #endif
2254 }
2255
2256 /*
2257 * Routines to render the lzss image format
2258 */
2259
2260 struct lzss_image_state {
2261 uint32_t col;
2262 uint32_t row;
2263 uint32_t width;
2264 uint32_t height;
2265 uint32_t bytes_per_row;
2266 volatile uint32_t * row_start;
2267 const uint8_t* clut;
2268 };
2269 typedef struct lzss_image_state lzss_image_state;
2270
2271 // returns 0 if OK, 1 if error
2272 static inline int
2273 vc_decompress_lzss_next_pixel (int next_data, lzss_image_state* state)
2274 {
2275 uint32_t palette_index = 0;
2276 uint32_t pixel_value = 0;
2277
2278 palette_index = next_data * 3;
2279
2280 pixel_value = ( (uint32_t) state->clut[palette_index + 0] << 16)
2281 | ( (uint32_t) state->clut[palette_index + 1] << 8)
2282 | ( (uint32_t) state->clut[palette_index + 2]);
2283
2284 *(state->row_start + state->col) = pixel_value;
2285
2286 if (++state->col >= state->width) {
2287 state->col = 0;
2288 if (++state->row >= state->height) {
2289 return 1;
2290 }
2291 state->row_start = (volatile uint32_t *) (((uintptr_t)state->row_start) + state->bytes_per_row);
2292 }
2293 return 0;
2294 }
2295
2296
2297 /*
2298 * Blit an lzss compressed image to the framebuffer
2299 * Assumes 32 bit screen (which is everything we ship at the moment)
2300 * The function vc_display_lzss_icon was copied from libkern/mkext.c, then modified.
2301 */
2302
2303 /*
2304 * TODO: Does lzss use too much stack? 4096 plus bytes...
2305 * Can probably chop it down by 1/2.
2306 */
2307
2308 /**************************************************************
2309 LZSS.C -- A Data Compression Program
2310 ***************************************************************
2311 4/6/1989 Haruhiko Okumura
2312 Use, distribute, and modify this program freely.
2313 Please send me your improved versions.
2314 PC-VAN SCIENCE
2315 NIFTY-Serve PAF01022
2316 CompuServe 74050,1022
2317
2318 **************************************************************/
2319
2320 #define N 4096 /* size of ring buffer - must be power of 2 */
2321 #define F 18 /* upper limit for match_length */
2322 #define THRESHOLD 2 /* encode string into position and length
2323 if match_length is greater than this */
2324
2325 // returns 0 if OK, 1 if error
2326 // x and y indicate upper left corner of image location on screen
2327 int
2328 vc_display_lzss_icon(uint32_t dst_x, uint32_t dst_y,
2329 uint32_t image_width, uint32_t image_height,
2330 const uint8_t *compressed_image,
2331 uint32_t compressed_size,
2332 const uint8_t *clut)
2333 {
2334 uint32_t* image_start;
2335 uint32_t bytes_per_pixel = 4;
2336 uint32_t bytes_per_row = vinfo.v_rowbytes;
2337
2338 vc_clean_boot_graphics();
2339
2340 image_start = (uint32_t *) (vinfo.v_baseaddr + (dst_y * bytes_per_row) + (dst_x * bytes_per_pixel));
2341
2342 lzss_image_state state = {0, 0, image_width, image_height, bytes_per_row, image_start, clut};
2343
2344 int rval = 0;
2345
2346 const uint8_t *src = compressed_image;
2347 uint32_t srclen = compressed_size;
2348
2349 /* ring buffer of size N, with extra F-1 bytes to aid string comparison */
2350 uint8_t text_buf[N + F - 1];
2351 const uint8_t *srcend = src + srclen;
2352 int i, j, k, r, c;
2353 unsigned int flags;
2354
2355 srcend = src + srclen;
2356 for (i = 0; i < N - F; i++)
2357 text_buf[i] = ' ';
2358 r = N - F;
2359 flags = 0;
2360 for ( ; ; ) {
2361 if (((flags >>= 1) & 0x100) == 0) {
2362 if (src < srcend) c = *src++; else break;
2363 flags = c | 0xFF00; /* uses higher byte cleverly */
2364 } /* to count eight */
2365 if (flags & 1) {
2366 if (src < srcend) c = *src++; else break;
2367 rval = vc_decompress_lzss_next_pixel(c, &state);
2368 if (rval != 0)
2369 return rval;
2370 text_buf[r++] = c;
2371 r &= (N - 1);
2372 } else {
2373 if (src < srcend) i = *src++; else break;
2374 if (src < srcend) j = *src++; else break;
2375 i |= ((j & 0xF0) << 4);
2376 j = (j & 0x0F) + THRESHOLD;
2377 for (k = 0; k <= j; k++) {
2378 c = text_buf[(i + k) & (N - 1)];
2379 rval = vc_decompress_lzss_next_pixel(c, &state);
2380 if (rval != 0 )
2381 return rval;
2382 text_buf[r++] = c;
2383 r &= (N - 1);
2384 }
2385 }
2386 }
2387 return 0;
2388 }
2389
2390 void noroot_icon_test(void) {
2391 boolean_t o_vc_progress_enable = vc_progress_enable;
2392
2393 vc_progress_enable = 1;
2394
2395 PE_display_icon( 0, "noroot");
2396
2397 vc_progress_enable = o_vc_progress_enable;
2398 }
2399
2400
2401 void vc_display_icon( vc_progress_element * desc,
2402 const unsigned char * data )
2403 {
2404 int x, y, width, height;
2405
2406 if( vc_progress_enable && vc_clut) {
2407
2408 vc_clean_boot_graphics();
2409
2410 width = desc->width;
2411 height = desc->height;
2412 x = desc->dx;
2413 y = desc->dy;
2414 if( 1 & desc->flags) {
2415 x += ((vinfo.v_width - width) / 2);
2416 y += ((vinfo.v_height - height) / 2);
2417 }
2418 vc_blit_rect( x, y, 0, width, height, width, height, width, 0, data, NULL, kDataIndexed );
2419 }
2420 }
2421
2422 void
2423 vc_progress_initialize( vc_progress_element * desc,
2424 const unsigned char * data1x,
2425 const unsigned char * data2x,
2426 const unsigned char * data3x,
2427 const unsigned char * clut )
2428 {
2429 uint64_t abstime;
2430
2431 if( (!clut) || (!desc) || (!data1x))
2432 return;
2433 vc_clut = clut;
2434 vc_clut8 = clut;
2435
2436 vc_progress = desc;
2437 vc_progress_data[0] = data1x;
2438 vc_progress_data[1] = data2x;
2439 vc_progress_data[2] = data3x;
2440 if( 2 & vc_progress->flags)
2441 vc_progress_alpha = data1x
2442 + vc_progress->count * vc_progress->width * vc_progress->height;
2443 else
2444 vc_progress_alpha = NULL;
2445
2446 thread_call_setup(&vc_progress_call, vc_progress_task, NULL);
2447 clock_interval_to_absolutetime_interval(vc_progress->time, 1000 * 1000, &abstime);
2448 vc_progress_interval = (uint32_t)abstime;
2449
2450 #if !CONFIG_EMBEDDED
2451 thread_call_setup(&vc_progressmeter_call, vc_progressmeter_task, NULL);
2452 clock_interval_to_absolutetime_interval(1000 / 8, 1000 * 1000, &abstime);
2453 vc_progressmeter_interval = (uint32_t)abstime;
2454 #endif /* !CONFIG_EMBEDDED */
2455
2456 }
2457
2458 void
2459 vc_progress_set(boolean_t enable, uint32_t vc_delay)
2460 {
2461 spl_t s;
2462 void *saveBuf = NULL;
2463 vm_size_t saveLen = 0;
2464 unsigned int count;
2465 unsigned int index;
2466 unsigned char pdata8;
2467 unsigned short pdata16;
2468 unsigned short * buf16;
2469 unsigned int pdata32;
2470 unsigned int * buf32;
2471
2472 #if !CONFIG_EMBEDDED
2473
2474 if (kBootArgsFlagBlack & ((boot_args *) PE_state.bootArgs)->flags) return;
2475
2476 if (1 & vc_progress_withmeter)
2477 {
2478 if (enable) internal_enable_progressmeter(kProgressMeterKernel);
2479
2480 s = splhigh();
2481 simple_lock(&vc_progress_lock, LCK_GRP_NULL);
2482
2483 if( vc_progress_enable != enable) {
2484 vc_progress_enable = enable;
2485 if( enable)
2486 {
2487 vc_progressmeter_count = 0;
2488 clock_interval_to_deadline(vc_delay,
2489 1000 * 1000 * 1000 /*second scale*/,
2490 &vc_progressmeter_deadline);
2491 thread_call_enter_delayed(&vc_progressmeter_call, vc_progressmeter_deadline);
2492 }
2493 else thread_call_cancel(&vc_progressmeter_call);
2494 }
2495
2496 simple_unlock(&vc_progress_lock);
2497 splx(s);
2498
2499 if (!enable) internal_enable_progressmeter(kProgressMeterOff);
2500 return;
2501 }
2502
2503 #endif /* !CONFIG_EMBEDDED */
2504
2505 if(!vc_progress) return;
2506
2507 if( enable) {
2508 saveLen = (vc_progress->width * vc_uiscale) * (vc_progress->height * vc_uiscale) * ((vinfo.v_depth + 7) / 8);
2509 saveBuf = kalloc( saveLen );
2510
2511 switch( vinfo.v_depth) {
2512 case 8 :
2513 for( count = 0; count < 256; count++) {
2514 vc_revclut8[count] = vc_clut[0x01 * 3];
2515 pdata8 = (vc_clut[0x01 * 3] * count + 0x0ff) >> 8;
2516 for( index = 0; index < 256; index++) {
2517 if( (pdata8 == vc_clut[index * 3 + 0]) &&
2518 (pdata8 == vc_clut[index * 3 + 1]) &&
2519 (pdata8 == vc_clut[index * 3 + 2])) {
2520 vc_revclut8[count] = index;
2521 break;
2522 }
2523 }
2524 }
2525 memset( saveBuf, 0x01, saveLen );
2526 break;
2527
2528 case 16 :
2529 buf16 = (unsigned short *) saveBuf;
2530 pdata16 = ((vc_clut[0x01 * 3 + 0] & CLUT_MASK_R) CLUT_SHIFT_R)
2531 | ((vc_clut[0x01 * 3 + 0] & CLUT_MASK_G) CLUT_SHIFT_G)
2532 | ((vc_clut[0x01 * 3 + 0] & CLUT_MASK_B) CLUT_SHIFT_B);
2533 for( count = 0; count < saveLen / 2; count++)
2534 buf16[count] = pdata16;
2535 break;
2536
2537 case 32 :
2538 buf32 = (unsigned int *) saveBuf;
2539 pdata32 = ((vc_clut[0x01 * 3 + 0] & 0xff) << 16)
2540 | ((vc_clut[0x01 * 3 + 1] & 0xff) << 8)
2541 | ((vc_clut[0x01 * 3 + 2] & 0xff) << 0);
2542 for( count = 0; count < saveLen / 4; count++)
2543 buf32[count] = pdata32;
2544 break;
2545 }
2546 }
2547
2548 s = splhigh();
2549 simple_lock(&vc_progress_lock, LCK_GRP_NULL);
2550
2551 if( vc_progress_enable != enable) {
2552 vc_progress_enable = enable;
2553 if( enable) {
2554 vc_needsave = TRUE;
2555 vc_saveunder = saveBuf;
2556 vc_saveunder_len = saveLen;
2557 saveBuf = NULL;
2558 saveLen = 0;
2559 vc_progress_count = 0;
2560 vc_progress_angle = 0;
2561
2562 clock_interval_to_deadline(vc_delay,
2563 1000 * 1000 * 1000 /*second scale*/,
2564 &vc_progress_deadline);
2565 thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline);
2566
2567 } else {
2568 if( vc_saveunder) {
2569 saveBuf = vc_saveunder;
2570 saveLen = vc_saveunder_len;
2571 vc_saveunder = NULL;
2572 vc_saveunder_len = 0;
2573 }
2574
2575 thread_call_cancel(&vc_progress_call);
2576 }
2577 }
2578
2579 simple_unlock(&vc_progress_lock);
2580 splx(s);
2581
2582 if( saveBuf)
2583 kfree( saveBuf, saveLen );
2584 }
2585
2586 #if !CONFIG_EMBEDDED
2587
2588 static uint32_t vc_progressmeter_range(uint32_t pos)
2589 {
2590 uint32_t ret;
2591
2592 if (pos > kProgressMeterEnd) pos = kProgressMeterEnd;
2593 ret = vc_progress_meter_start
2594 + ((pos * (vc_progress_meter_end - vc_progress_meter_start)) / kProgressMeterEnd);
2595
2596 return (ret);
2597 }
2598
2599 static void
2600 vc_progressmeter_task(__unused void *arg0, __unused void *arg)
2601 {
2602 spl_t s;
2603 uint64_t interval;
2604
2605 s = splhigh();
2606 simple_lock(&vc_progress_lock, LCK_GRP_NULL);
2607 if (vc_progressmeter_enable)
2608 {
2609 uint32_t pos = (vc_progressmeter_count >> 13);
2610 internal_set_progressmeter(vc_progressmeter_range(pos));
2611 if (pos < kProgressMeterEnd)
2612 {
2613 static uint16_t incr[8] = { 10000, 10000, 8192, 4096, 2048, 384, 384, 64 };
2614 vc_progressmeter_count += incr[(pos * 8) / kProgressMeterEnd];
2615
2616 interval = vc_progressmeter_interval;
2617 interval = ((interval * 256) / vc_progressmeter_diskspeed);
2618
2619 clock_deadline_for_periodic_event(interval, mach_absolute_time(), &vc_progressmeter_deadline);
2620 thread_call_enter_delayed(&vc_progressmeter_call, vc_progressmeter_deadline);
2621 }
2622 }
2623 simple_unlock(&vc_progress_lock);
2624 splx(s);
2625 }
2626
2627 void vc_progress_setdiskspeed(uint32_t speed)
2628 {
2629 vc_progressmeter_diskspeed = speed;
2630 }
2631
2632 #endif /* !CONFIG_EMBEDDED */
2633
2634 static void
2635 vc_progress_task(__unused void *arg0, __unused void *arg)
2636 {
2637 spl_t s;
2638 int x, y, width, height;
2639 uint64_t x_pos, y_pos;
2640 const unsigned char * data;
2641
2642 s = splhigh();
2643 simple_lock(&vc_progress_lock, LCK_GRP_NULL);
2644
2645 if( vc_progress_enable) do {
2646
2647 vc_progress_count++;
2648 if( vc_progress_count >= vc_progress->count) {
2649 vc_progress_count = 0;
2650 vc_progress_angle++;
2651 }
2652
2653 width = (vc_progress->width * vc_uiscale);
2654 height = (vc_progress->height * vc_uiscale);
2655 data = vc_progress_data[vc_uiscale - 1];
2656 if (!data) break;
2657
2658 if (kVCUsePosition & vc_progress_options.options) {
2659 /* Rotation: 0:normal, 1:right 90, 2:left 180, 3:left 90 */
2660 switch (3 & vinfo.v_rotate) {
2661 case kDataRotate0:
2662 x_pos = vc_progress_options.x_pos;
2663 y_pos = vc_progress_options.y_pos;
2664 break;
2665 case kDataRotate180:
2666 x_pos = 0xFFFFFFFF - vc_progress_options.x_pos;
2667 y_pos = 0xFFFFFFFF - vc_progress_options.y_pos;
2668 break;
2669 case kDataRotate90:
2670 x_pos = 0xFFFFFFFF - vc_progress_options.y_pos;
2671 y_pos = vc_progress_options.x_pos;
2672 break;
2673 case kDataRotate270:
2674 x_pos = vc_progress_options.y_pos;
2675 y_pos = 0xFFFFFFFF - vc_progress_options.x_pos;
2676 break;
2677 }
2678 x = (uint32_t)((x_pos * (uint64_t) vinfo.v_width) / 0xFFFFFFFFULL);
2679 y = (uint32_t)((y_pos * (uint64_t) vinfo.v_height) / 0xFFFFFFFFULL);
2680 x -= (width / 2);
2681 y -= (height / 2);
2682 } else {
2683 x = (vc_progress->dx * vc_uiscale);
2684 y = (vc_progress->dy * vc_uiscale);
2685 if( 1 & vc_progress->flags) {
2686 x += ((vinfo.v_width - width) / 2);
2687 y += ((vinfo.v_height - height) / 2);
2688 }
2689 }
2690
2691 if ((x + width) > (int)vinfo.v_width) break;
2692 if ((y + height) > (int)vinfo.v_height) break;
2693
2694 data += vc_progress_count * width * height;
2695
2696 vc_blit_rect( x, y, 0,
2697 width, height, width, height, width, width,
2698 data, vc_saveunder,
2699 kDataAlpha
2700 | (vc_progress_angle & kDataRotate)
2701 | (vc_needsave ? kSave : 0) );
2702 vc_needsave = FALSE;
2703
2704 clock_deadline_for_periodic_event(vc_progress_interval, mach_absolute_time(), &vc_progress_deadline);
2705 thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline);
2706 }
2707 while (FALSE);
2708 simple_unlock(&vc_progress_lock);
2709 splx(s);
2710 }
2711
2712 /*
2713 * Generic Console (Front-End): Master Control
2714 * -------------------------------------------
2715 */
2716
2717 #if defined (__i386__) || defined (__x86_64__)
2718 #include <pexpert/i386/boot.h>
2719 #endif
2720
2721 static boolean_t gc_acquired = FALSE;
2722 static boolean_t gc_graphics_boot = FALSE;
2723 static boolean_t gc_desire_text = FALSE;
2724 static boolean_t gc_paused_progress;
2725
2726 static vm_offset_t lastVideoVirt = 0;
2727 static vm_size_t lastVideoMapSize = 0;
2728 static boolean_t lastVideoMapKmap = FALSE;
2729
2730 static void
2731 gc_pause( boolean_t pause, boolean_t graphics_now )
2732 {
2733 spl_t s;
2734
2735 s = splhigh( );
2736 VCPUTC_LOCK_LOCK( );
2737
2738 disableConsoleOutput = (pause && !console_is_serial());
2739 gc_enabled = (!pause && !graphics_now);
2740
2741 VCPUTC_LOCK_UNLOCK( );
2742
2743 simple_lock(&vc_progress_lock, LCK_GRP_NULL);
2744
2745 if (pause)
2746 {
2747 gc_paused_progress = vc_progress_enable;
2748 vc_progress_enable = FALSE;
2749 }
2750 else vc_progress_enable = gc_paused_progress;
2751
2752 if (vc_progress_enable)
2753 {
2754 #if !CONFIG_EMBEDDED
2755 if (1 & vc_progress_withmeter) thread_call_enter_delayed(&vc_progressmeter_call, vc_progressmeter_deadline);
2756 else
2757 #endif /* !CONFIG_EMBEDDED */
2758 thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline);
2759 }
2760
2761 simple_unlock(&vc_progress_lock);
2762 splx(s);
2763 }
2764
2765 static void
2766 vc_initialize(__unused struct vc_info * vinfo_p)
2767 {
2768 #ifdef __arm__
2769 unsigned long cnt, data16, data32;
2770
2771 if (vinfo.v_depth == 16) {
2772 for (cnt = 0; cnt < 8; cnt++) {
2773 data32 = vc_colors[cnt][2];
2774 data16 = (data32 & 0x0000F8) << 8;
2775 data16 |= (data32 & 0x00FC00) >> 5;
2776 data16 |= (data32 & 0xF80000) >> 19;
2777 data16 |= data16 << 16;
2778 vc_colors[cnt][1] = data16;
2779 }
2780 }
2781 #endif
2782
2783 vinfo.v_rows = vinfo.v_height / ISO_CHAR_HEIGHT;
2784 vinfo.v_columns = vinfo.v_width / ISO_CHAR_WIDTH;
2785 vinfo.v_rowscanbytes = ((vinfo.v_depth + 7) / 8) * vinfo.v_width;
2786 vc_uiscale = vinfo.v_scale;
2787 if (vc_uiscale > kMaxProgressData) vc_uiscale = kMaxProgressData;
2788 else if (!vc_uiscale) vc_uiscale = 1;
2789 }
2790
2791 void
2792 initialize_screen(PE_Video * boot_vinfo, unsigned int op)
2793 {
2794 unsigned int newMapSize = 0;
2795 vm_offset_t newVideoVirt = 0;
2796 boolean_t graphics_now;
2797 uint32_t delay;
2798
2799 if ( boot_vinfo )
2800 {
2801 struct vc_info new_vinfo = vinfo;
2802 boolean_t makeMapping = FALSE;
2803
2804 /*
2805 * Copy parameters
2806 */
2807 if (kPEBaseAddressChange != op)
2808 {
2809 new_vinfo.v_width = (unsigned int)boot_vinfo->v_width;
2810 new_vinfo.v_height = (unsigned int)boot_vinfo->v_height;
2811 new_vinfo.v_depth = (unsigned int)boot_vinfo->v_depth;
2812 new_vinfo.v_rowbytes = (unsigned int)boot_vinfo->v_rowBytes;
2813 if (kernel_map == VM_MAP_NULL) {
2814 // only booter supplies HW rotation
2815 new_vinfo.v_rotate = (unsigned int)boot_vinfo->v_rotate;
2816 }
2817 #if defined(__i386__) || defined(__x86_64__)
2818 new_vinfo.v_type = (unsigned int)boot_vinfo->v_display;
2819 #else
2820 new_vinfo.v_type = 0;
2821 #endif
2822 unsigned int scale = (unsigned int)boot_vinfo->v_scale;
2823 if (scale == kPEScaleFactor1x )
2824 new_vinfo.v_scale = kPEScaleFactor1x;
2825 else if (scale == kPEScaleFactor2x)
2826 new_vinfo.v_scale = kPEScaleFactor2x;
2827 else /* Scale factor not set, default to 1x */
2828 new_vinfo.v_scale = kPEScaleFactor1x;
2829 }
2830 new_vinfo.v_name[0] = 0;
2831 new_vinfo.v_physaddr = 0;
2832
2833 /*
2834 * Check if we are have to map the framebuffer
2835 * If VM is up, we are given a virtual address, unless b0 is set to indicate physical.
2836 */
2837 newVideoVirt = boot_vinfo->v_baseAddr;
2838 makeMapping = (kernel_map == VM_MAP_NULL) || (0 != (1 & newVideoVirt));
2839 if (makeMapping)
2840 {
2841 newVideoVirt = 0;
2842 new_vinfo.v_physaddr = boot_vinfo->v_baseAddr & ~3UL; /* Get the physical address */
2843 #ifndef __LP64__
2844 new_vinfo.v_physaddr |= (((uint64_t) boot_vinfo->v_baseAddrHigh) << 32);
2845 #endif
2846 kprintf("initialize_screen: b=%08llX, w=%08X, h=%08X, r=%08X, d=%08X\n", /* (BRINGUP) */
2847 new_vinfo.v_physaddr, new_vinfo.v_width, new_vinfo.v_height, new_vinfo.v_rowbytes, new_vinfo.v_type); /* (BRINGUP) */
2848 }
2849
2850 if (!newVideoVirt && !new_vinfo.v_physaddr) /* Check to see if we have a framebuffer */
2851 {
2852 kprintf("initialize_screen: No video - forcing serial mode\n"); /* (BRINGUP) */
2853 new_vinfo.v_depth = 0; /* vc routines are nop */
2854 (void)switch_to_serial_console(); /* Switch into serial mode */
2855 gc_graphics_boot = FALSE; /* Say we are not in graphics mode */
2856 disableConsoleOutput = FALSE; /* Allow printfs to happen */
2857 gc_acquired = TRUE;
2858 }
2859 else
2860 {
2861 if (makeMapping)
2862 {
2863 unsigned int flags = VM_WIMG_IO;
2864 if (boot_vinfo->v_length != 0)
2865 newMapSize = (unsigned int) round_page(boot_vinfo->v_length);
2866 else
2867 newMapSize = (unsigned int) round_page(new_vinfo.v_height * new_vinfo.v_rowbytes); /* Remember size */
2868 newVideoVirt = io_map_spec((vm_map_offset_t)new_vinfo.v_physaddr, newMapSize, flags); /* Allocate address space for framebuffer */
2869 }
2870 new_vinfo.v_baseaddr = newVideoVirt + boot_vinfo->v_offset; /* Set the new framebuffer address */
2871 }
2872
2873 #if defined(__x86_64__)
2874 // Adjust the video buffer pointer to point to where it is in high virtual (above the hole)
2875 new_vinfo.v_baseaddr |= (VM_MIN_KERNEL_ADDRESS & ~LOW_4GB_MASK);
2876 #endif
2877
2878 /* Update the vinfo structure atomically with respect to the vc_progress task if running */
2879 if (vc_progress)
2880 {
2881 simple_lock(&vc_progress_lock, LCK_GRP_NULL);
2882 vinfo = new_vinfo;
2883 simple_unlock(&vc_progress_lock);
2884 }
2885 else
2886 {
2887 vinfo = new_vinfo;
2888 }
2889
2890 // If we changed the virtual address, remove the old mapping
2891 if (newVideoVirt != 0)
2892 {
2893 if (lastVideoVirt && lastVideoMapSize) /* Was the framebuffer mapped before? */
2894 {
2895 /* XXX why only !4K? */
2896 if (!TEST_PAGE_SIZE_4K && lastVideoMapSize)
2897 {
2898 pmap_remove(kernel_pmap, trunc_page_64(lastVideoVirt),
2899 round_page_64(lastVideoVirt + lastVideoMapSize)); /* Toss mappings */
2900 }
2901 /* Was this not a special pre-VM mapping? */
2902 if (lastVideoMapKmap)
2903 {
2904 kmem_free(kernel_map, lastVideoVirt, lastVideoMapSize); /* Toss kernel addresses */
2905 }
2906 }
2907 lastVideoMapKmap = (NULL != kernel_map); /* Remember how mapped */
2908 lastVideoMapSize = newMapSize; /* Remember the size */
2909 lastVideoVirt = newVideoVirt; /* Remember the virtual framebuffer address */
2910 }
2911
2912 if (kPEBaseAddressChange != op)
2913 {
2914 // Graphics mode setup by the booter.
2915
2916 gc_ops.initialize = vc_initialize;
2917 gc_ops.enable = vc_enable;
2918 gc_ops.paint_char = vc_paint_char;
2919 gc_ops.scroll_down = vc_scroll_down;
2920 gc_ops.scroll_up = vc_scroll_up;
2921 gc_ops.clear_screen = vc_clear_screen;
2922 gc_ops.hide_cursor = vc_reverse_cursor;
2923 gc_ops.show_cursor = vc_reverse_cursor;
2924 gc_ops.update_color = vc_update_color;
2925 gc_initialize(&vinfo);
2926 }
2927 }
2928
2929 graphics_now = gc_graphics_boot && !gc_desire_text;
2930 switch ( op )
2931 {
2932 case kPEGraphicsMode:
2933 gc_graphics_boot = TRUE;
2934 gc_desire_text = FALSE;
2935 break;
2936
2937 case kPETextMode:
2938 gc_graphics_boot = FALSE;
2939 break;
2940
2941 case kPEAcquireScreen:
2942 if ( gc_acquired ) break;
2943
2944 vc_progress_options = vc_user_options;
2945 bzero(&vc_user_options, sizeof(vc_user_options));
2946
2947 if (kVCAcquireImmediate & vc_progress_options.options) delay = 0;
2948 else if (kVCDarkReboot & vc_progress_options.options) delay = 120;
2949 else delay = vc_acquire_delay;
2950
2951 if (kVCDarkBackground & vc_progress_options.options) vc_progress_white = TRUE;
2952 else if (kVCLightBackground & vc_progress_options.options) vc_progress_white = FALSE;
2953
2954 #if !defined(XNU_TARGET_OS_BRIDGE)
2955 vc_progress_set( graphics_now, delay );
2956 #endif /* !defined(XNU_TARGET_OS_BRIDGE) */
2957 gc_enable( !graphics_now );
2958 gc_acquired = TRUE;
2959 gc_desire_text = FALSE;
2960 break;
2961
2962 case kPEDisableScreen:
2963 if (gc_acquired)
2964 {
2965 gc_pause( TRUE, graphics_now );
2966 }
2967 break;
2968
2969 case kPEEnableScreen:
2970 if (gc_acquired)
2971 {
2972 gc_pause( FALSE, graphics_now );
2973 }
2974 break;
2975
2976 case kPETextScreen:
2977 if ( console_is_serial() ) break;
2978
2979 if ( gc_acquired == FALSE )
2980 {
2981 gc_desire_text = TRUE;
2982 break;
2983 }
2984 if ( gc_graphics_boot == FALSE ) break;
2985
2986 vc_progress_set( FALSE, 0 );
2987 #if !CONFIG_EMBEDDED
2988 vc_enable_progressmeter( FALSE );
2989 #endif
2990 gc_enable( TRUE );
2991 break;
2992
2993 case kPEReleaseScreen:
2994 gc_acquired = FALSE;
2995 gc_desire_text = FALSE;
2996 gc_enable( FALSE );
2997 if ( gc_graphics_boot == FALSE ) break;
2998
2999 vc_progress_set( FALSE, 0 );
3000 vc_acquire_delay = kProgressReacquireDelay;
3001 vc_progress_white = TRUE;
3002 #if !CONFIG_EMBEDDED
3003 vc_enable_progressmeter(FALSE);
3004 vc_progress_withmeter &= ~1;
3005 #endif
3006 vc_clut8 = NULL;
3007 break;
3008
3009
3010 #if !CONFIG_EMBEDDED
3011 case kPERefreshBootGraphics:
3012 {
3013 spl_t s;
3014 boolean_t save;
3015
3016 if (kBootArgsFlagBlack & ((boot_args *) PE_state.bootArgs)->flags) break;
3017
3018 save = vc_progress_white;
3019 vc_progress_white = (0 != (kBootArgsFlagBlackBg & ((boot_args *) PE_state.bootArgs)->flags));
3020
3021 internal_enable_progressmeter(kProgressMeterKernel);
3022
3023 s = splhigh();
3024 simple_lock(&vc_progress_lock, LCK_GRP_NULL);
3025
3026 vc_progressmeter_drawn = 0;
3027 internal_set_progressmeter(vc_progressmeter_range(vc_progressmeter_count >> 13));
3028
3029 simple_unlock(&vc_progress_lock);
3030 splx(s);
3031
3032 internal_enable_progressmeter(kProgressMeterOff);
3033 vc_progress_white = save;
3034 }
3035 #endif
3036 }
3037 }
3038
3039 void vcattach(void); /* XXX gcc 4 warning cleanup */
3040
3041 void
3042 vcattach(void)
3043 {
3044 vm_initialized = TRUE;
3045
3046 #if !CONFIG_EMBEDDED
3047 const boot_args * bootargs = (typeof(bootargs)) PE_state.bootArgs;
3048
3049 vc_progress_white = (0 != ((kBootArgsFlagBlackBg | kBootArgsFlagLoginUI)
3050 & bootargs->flags));
3051 PE_parse_boot_argn("meter", &vc_progress_withmeter, sizeof(vc_progress_withmeter));
3052
3053 if (kBootArgsFlagInstallUI & bootargs->flags)
3054 {
3055 vc_progress_meter_start = (bootargs->bootProgressMeterStart * kProgressMeterMax) / 65535;
3056 vc_progress_meter_end = (bootargs->bootProgressMeterEnd * kProgressMeterMax) / 65535;
3057 }
3058 else
3059 {
3060 vc_progress_meter_start = 0;
3061 vc_progress_meter_end = kProgressMeterMax;
3062 }
3063 #endif
3064 simple_lock_init(&vc_progress_lock, 0);
3065
3066 if ( gc_graphics_boot == FALSE )
3067 {
3068 long index;
3069
3070 if ( gc_acquired )
3071 {
3072 initialize_screen(NULL, kPEReleaseScreen);
3073 }
3074
3075 initialize_screen(NULL, kPEAcquireScreen);
3076
3077 for ( index = 0 ; index < msgbufp->msg_bufx ; index++ )
3078 {
3079 if (msgbufp->msg_bufc[index] == '\0') {
3080 continue;
3081 }
3082
3083 vcputc( 0, 0, msgbufp->msg_bufc[index] );
3084
3085 if ( msgbufp->msg_bufc[index] == '\n' )
3086 {
3087 vcputc( 0, 0,'\r' );
3088 }
3089 }
3090 }
3091 }
3092
3093 #if !CONFIG_EMBEDDED
3094
3095 // redraw progress meter between pixels start, end, position at pos,
3096 // options (including rotation) passed in flags
3097 static void
3098 vc_draw_progress_meter(unsigned int flags, int start, int end, int pos)
3099 {
3100 const unsigned char *data;
3101 int i, width, bx, srcRow, backRow;
3102 int rectX, rectY, rectW, rectH;
3103 int endCapPos, endCapStart;
3104 int barWidth = kProgressBarWidth * vc_uiscale;
3105 int barHeight = kProgressBarHeight * vc_uiscale;
3106 int capWidth = kProgressBarCapWidth * vc_uiscale;
3107 // 1 rounded fill, 0 square end
3108 int style = (0 == (2 & vc_progress_withmeter));
3109 // 1 white, 0 greyed out
3110 int onoff;
3111
3112 for (i = start; i < end; i += width)
3113 {
3114 onoff = (i < pos);
3115 endCapPos = ((style && onoff) ? pos : barWidth);
3116 endCapStart = endCapPos - capWidth;
3117 if (flags & kDataBack) { // restore back bits
3118 width = end; // loop done after this iteration
3119 data = NULL;
3120 srcRow = 0;
3121 } else if (i < capWidth) { // drawing the left cap
3122 width = (end < capWidth) ? (end - i) : (capWidth - i);
3123 data = progressmeter_leftcap[vc_uiscale >= 2][onoff];
3124 data += i;
3125 srcRow = capWidth;
3126 } else if (i < endCapStart) { // drawing the middle
3127 width = (end < endCapStart) ? (end - i) : (endCapStart - i);
3128 data = progressmeter_middle[vc_uiscale >= 2][onoff];
3129 srcRow = 1;
3130 } else { // drawing the right cap
3131 width = endCapPos - i;
3132 data = progressmeter_rightcap[vc_uiscale >= 2][onoff];
3133 data += i - endCapStart;
3134 srcRow = capWidth;
3135 }
3136
3137 switch (flags & kDataRotate) {
3138 case kDataRotate90: // left middle, bar goes down
3139 rectW = barHeight;
3140 rectH = width;
3141 rectX = ((vinfo.v_width / 3) - (barHeight / 2));
3142 rectY = ((vinfo.v_height - barWidth) / 2) + i;
3143 bx = i * barHeight;
3144 backRow = barHeight;
3145 break;
3146 case kDataRotate180: // middle upper, bar goes left
3147 rectW = width;
3148 rectH = barHeight;
3149 rectX = ((vinfo.v_width - barWidth) / 2) + barWidth - width - i;
3150 rectY = (vinfo.v_height / 3) - (barHeight / 2);
3151 bx = barWidth - width - i;
3152 backRow = barWidth;
3153 break;
3154 case kDataRotate270: // right middle, bar goes up
3155 rectW = barHeight;
3156 rectH = width;
3157 rectX = (vinfo.v_width - (vinfo.v_width / 3) - (barHeight / 2));
3158 rectY = ((vinfo.v_height - barWidth) / 2) + barWidth - width - i;
3159 bx = (barWidth - width - i) * barHeight;
3160 backRow = barHeight;
3161 break;
3162 default:
3163 case kDataRotate0: // middle lower, bar goes right
3164 rectW = width;
3165 rectH = barHeight;
3166 rectX = ((vinfo.v_width - barWidth) / 2) + i;
3167 rectY = vinfo.v_height - (vinfo.v_height / 3) - (barHeight / 2);
3168 bx = i;
3169 backRow = barWidth;
3170 break;
3171 }
3172 vc_blit_rect(rectX, rectY, bx, rectW, rectH, width, barHeight,
3173 srcRow, backRow, data, vc_progressmeter_backbuffer, flags);
3174 }
3175 }
3176
3177 extern void IORecordProgressBackbuffer(void * buffer, size_t size, uint32_t theme);
3178
3179 static void
3180 internal_enable_progressmeter(int new_value)
3181 {
3182 spl_t s;
3183 void * new_buffer;
3184 boolean_t stashBackbuffer;
3185 int flags = vinfo.v_rotate;
3186
3187 stashBackbuffer = FALSE;
3188 new_buffer = NULL;
3189 if (new_value)
3190 {
3191 new_buffer = kalloc((kProgressBarWidth * vc_uiscale)
3192 * (kProgressBarHeight * vc_uiscale) * sizeof(int));
3193 }
3194
3195 s = splhigh();
3196 simple_lock(&vc_progress_lock, LCK_GRP_NULL);
3197
3198 if (kProgressMeterUser == new_value)
3199 {
3200 if (gc_enabled || !gc_acquired || !gc_graphics_boot
3201 || (kProgressMeterKernel == vc_progressmeter_enable)) new_value = vc_progressmeter_enable;
3202 }
3203
3204 if (new_value != vc_progressmeter_enable)
3205 {
3206 if (new_value)
3207 {
3208 if (kProgressMeterOff == vc_progressmeter_enable)
3209 {
3210 vc_progressmeter_backbuffer = new_buffer;
3211 vc_draw_progress_meter(kDataAlpha | kSave | flags, 0, (kProgressBarWidth * vc_uiscale), 0);
3212 new_buffer = NULL;
3213 vc_progressmeter_drawn = 0;
3214 }
3215 vc_progressmeter_enable = new_value;
3216 }
3217 else if (vc_progressmeter_backbuffer)
3218 {
3219 if (kProgressMeterUser == vc_progressmeter_enable)
3220 {
3221 vc_draw_progress_meter(kDataBack | flags, 0, (kProgressBarWidth * vc_uiscale), vc_progressmeter_drawn);
3222 }
3223 else stashBackbuffer = TRUE;
3224 new_buffer = vc_progressmeter_backbuffer;
3225 vc_progressmeter_backbuffer = NULL;
3226 vc_progressmeter_enable = FALSE;
3227 }
3228 }
3229
3230 simple_unlock(&vc_progress_lock);
3231 splx(s);
3232
3233 if (new_buffer)
3234 {
3235 if (stashBackbuffer) IORecordProgressBackbuffer(new_buffer,
3236 (kProgressBarWidth * vc_uiscale)
3237 * (kProgressBarHeight * vc_uiscale)
3238 * sizeof(int),
3239 vc_progress_white);
3240 kfree(new_buffer, (kProgressBarWidth * vc_uiscale)
3241 * (kProgressBarHeight * vc_uiscale) * sizeof(int));
3242 }
3243 }
3244
3245 static void
3246 internal_set_progressmeter(int new_value)
3247 {
3248 int x1, x3;
3249 int capRedraw;
3250 // 1 rounded fill, 0 square end
3251 int style = (0 == (2 & vc_progress_withmeter));
3252 int flags = kDataAlpha | vinfo.v_rotate;
3253
3254 if ((new_value < 0) || (new_value > kProgressMeterMax)) return;
3255
3256 if (vc_progressmeter_enable)
3257 {
3258 vc_progressmeter_value = new_value;
3259
3260 capRedraw = (style ? (kProgressBarCapWidth * vc_uiscale) : 0);
3261 x3 = (((kProgressBarWidth * vc_uiscale) - 2 * capRedraw) * vc_progressmeter_value) / kProgressMeterMax;
3262 x3 += (2 * capRedraw);
3263
3264 if (x3 > vc_progressmeter_drawn)
3265 {
3266 x1 = capRedraw;
3267 if (x1 > vc_progressmeter_drawn) x1 = vc_progressmeter_drawn;
3268 vc_draw_progress_meter(flags, vc_progressmeter_drawn - x1, x3, x3);
3269 }
3270 else
3271 {
3272 vc_draw_progress_meter(flags, x3 - capRedraw, vc_progressmeter_drawn, x3);
3273 }
3274 vc_progressmeter_drawn = x3;
3275 }
3276 }
3277
3278 void
3279 vc_enable_progressmeter(int new_value)
3280 {
3281 if (kProgressMeterKernel == vc_progressmeter_enable)
3282 {
3283 vc_progressmeter_hold = new_value;
3284 }
3285 else
3286 {
3287 internal_enable_progressmeter(new_value ? kProgressMeterUser : kProgressMeterOff);
3288 }
3289 }
3290
3291 void
3292 vc_set_progressmeter(int new_value)
3293 {
3294 spl_t s;
3295
3296 s = splhigh();
3297 simple_lock(&vc_progress_lock, LCK_GRP_NULL);
3298
3299 if (vc_progressmeter_enable && (kProgressMeterKernel != vc_progressmeter_enable))
3300 {
3301 internal_set_progressmeter((new_value * kProgressMeterMax) / 100);
3302 }
3303
3304 simple_unlock(&vc_progress_lock);
3305 splx(s);
3306 }
3307
3308 #endif /* !CONFIG_EMBEDDED */
3309
3310
3311