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