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