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