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