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