]> git.saurik.com Git - apple/xnu.git/blame - osfmk/console/video_console.c
xnu-3247.1.106.tar.gz
[apple/xnu.git] / osfmk / console / video_console.c
CommitLineData
55e303ae 1/*
b0d623f7 2 * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
55e303ae 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
55e303ae 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
55e303ae
A
27 */
28/*
29 * @OSF_FREE_COPYRIGHT@
30 *
31 */
32/*
33 * @APPLE_FREE_COPYRIGHT@
34 */
35/*
36 * NetBSD: ite.c,v 1.16 1995/07/17 01:24:34 briggs Exp
37 *
38 * Copyright (c) 1988 University of Utah.
39 * Copyright (c) 1990, 1993
40 * The Regents of the University of California. All rights reserved.
41 *
42 * This code is derived from software contributed to Berkeley by
43 * the Systems Programming Group of the University of Utah Computer
44 * Science Department.
45 *
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
48 * are met:
49 * 1. Redistributions of source code must retain the above copyright
50 * notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright
52 * notice, this list of conditions and the following disclaimer in the
53 * documentation and/or other materials provided with the distribution.
54 * 3. All advertising materials mentioning features or use of this software
55 * must display the following acknowledgement:
56 * This product includes software developed by the University of
57 * California, Berkeley and its contributors.
58 * 4. Neither the name of the University nor the names of its contributors
59 * may be used to endorse or promote products derived from this software
60 * without specific prior written permission.
61 *
62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72 * SUCH DAMAGE.
73 *
74 * from: Utah $Hdr: ite.c 1.28 92/12/20$
75 *
76 * @(#)ite.c 8.2 (Berkeley) 1/12/94
77 */
78
79/*
80 * ite.c
81 *
82 * The ite module handles the system console; that is, stuff printed
83 * by the kernel and by user programs while "desktop" and X aren't
84 * running. Some (very small) parts are based on hp300's 4.4 ite.c,
85 * hence the above copyright.
86 *
87 * -- Brad and Lawrence, June 26th, 1994
88 *
89 */
90
55e303ae 91#include <console/video_console.h>
2d21ac55 92#include <console/serial_protos.h>
91447636
A
93
94#include <kern/kern_types.h>
95#include <kern/kalloc.h>
55e303ae 96#include <kern/debug.h>
55e303ae 97#include <kern/spl.h>
91447636
A
98#include <kern/thread_call.h>
99
100#include <vm/pmap.h>
55e303ae 101#include <vm/vm_kern.h>
0c530ab8 102#include <machine/io_map_entries.h>
2d21ac55 103#include <machine/machine_cpu.h>
91447636 104
55e303ae 105#include <pexpert/pexpert.h>
b0d623f7 106#include <sys/kdebug.h>
55e303ae
A
107
108#include "iso_font.c"
b0d623f7 109#include "progress_meter_data.c"
55e303ae 110
2d21ac55
A
111#include "sys/msgbuf.h"
112
55e303ae
A
113/*
114 * Generic Console (Front-End)
115 * ---------------------------
116 */
117
118struct vc_info vinfo;
55e303ae 119
7ddcb079
A
120void noroot_icon_test(void);
121
7ddcb079 122
55e303ae
A
123extern int disableConsoleOutput;
124static boolean_t gc_enabled = FALSE;
125static boolean_t gc_initialized = FALSE;
126static boolean_t vm_initialized = FALSE;
127
128static struct {
129 void (*initialize)(struct vc_info * info);
130 void (*enable)(boolean_t enable);
2d21ac55
A
131 void (*paint_char)(unsigned int xx, unsigned int yy, unsigned char ch,
132 int attrs, unsigned char ch_previous,
133 int attrs_previous);
134 void (*clear_screen)(unsigned int xx, unsigned int yy, unsigned int top,
135 unsigned int bottom, int which);
136 void (*scroll_down)(int num, unsigned int top, unsigned int bottom);
137 void (*scroll_up)(int num, unsigned int top, unsigned int bottom);
138 void (*hide_cursor)(unsigned int xx, unsigned int yy);
139 void (*show_cursor)(unsigned int xx, unsigned int yy);
55e303ae
A
140 void (*update_color)(int color, boolean_t fore);
141} gc_ops;
142
2d21ac55
A
143static unsigned char *gc_buffer_attributes;
144static unsigned char *gc_buffer_characters;
145static unsigned char *gc_buffer_colorcodes;
060df5ea 146static unsigned char *gc_buffer_tab_stops;
b0d623f7
A
147static uint32_t gc_buffer_columns;
148static uint32_t gc_buffer_rows;
149static uint32_t gc_buffer_size;
2d21ac55 150
060df5ea 151#if defined(__i386__) || defined(__x86_64__)
2d21ac55
A
152decl_simple_lock_data(static, vcputc_lock);
153
154#define VCPUTC_LOCK_INIT() \
155MACRO_BEGIN \
156 simple_lock_init(&vcputc_lock, 0); \
157MACRO_END
158
159#define VCPUTC_LOCK_LOCK() \
160MACRO_BEGIN \
161 boolean_t istate = ml_get_interrupts_enabled(); \
162 while (!simple_lock_try(&vcputc_lock)) \
163 { \
164 if (!istate) \
165 handle_pending_TLB_flushes(); \
166 cpu_pause(); \
167 } \
168MACRO_END
169
170#define VCPUTC_LOCK_UNLOCK() \
171MACRO_BEGIN \
172 simple_unlock(&vcputc_lock); \
173MACRO_END
174#else
175static hw_lock_data_t vcputc_lock;
176
177#define VCPUTC_LOCK_INIT() \
178MACRO_BEGIN \
179 hw_lock_init(&vcputc_lock); \
180MACRO_END
181
182#define VCPUTC_LOCK_LOCK() \
183MACRO_BEGIN \
39236c6e 184 if (!hw_lock_to(&vcputc_lock, ~0U))\
2d21ac55
A
185 { \
186 panic("VCPUTC_LOCK_LOCK"); \
187 } \
188MACRO_END
189
190#define VCPUTC_LOCK_UNLOCK() \
191MACRO_BEGIN \
192 hw_lock_unlock(&vcputc_lock); \
193MACRO_END
194#endif
55e303ae
A
195
196/*
197# Attribute codes:
198# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
199# Text color codes:
200# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
201# Background color codes:
202# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
203*/
204
205#define ATTR_NONE 0
206#define ATTR_BOLD 1
207#define ATTR_UNDER 2
208#define ATTR_REVERSE 4
209
210#define COLOR_BACKGROUND 0
211#define COLOR_FOREGROUND 7
212
213#define COLOR_CODE_GET(code, fore) (((code) & ((fore) ? 0xF0 : 0x0F)) >> ((fore) ? 4 : 0))
214#define COLOR_CODE_SET(code, color, fore) (((code) & ((fore) ? 0x0F : 0xF0)) | ((color) << ((fore) ? 4 : 0)))
215
2d21ac55 216static unsigned char gc_color_code;
55e303ae
A
217
218/* VT100 state: */
219#define MAXPARS 16
2d21ac55
A
220static unsigned int gc_x, gc_y, gc_savex, gc_savey;
221static unsigned int gc_par[MAXPARS], gc_numpars, gc_hanging_cursor, gc_attr, gc_saveattr;
55e303ae 222
060df5ea 223/* VT100 scroll region */
2d21ac55 224static unsigned int gc_scrreg_top, gc_scrreg_bottom;
55e303ae
A
225
226enum vt100state_e {
227 ESnormal, /* Nothing yet */
228 ESesc, /* Got ESC */
229 ESsquare, /* Got ESC [ */
230 ESgetpars, /* About to get or getting the parameters */
231 ESgotpars, /* Finished getting the parameters */
232 ESfunckey, /* Function key */
233 EShash, /* DEC-specific stuff (screen align, etc.) */
234 ESsetG0, /* Specify the G0 character set */
235 ESsetG1, /* Specify the G1 character set */
236 ESask,
237 EScharsize,
238 ESignore /* Ignore this sequence */
239} gc_vt100state = ESnormal;
240
13f56ec4 241
fe8ab488
A
242enum
243{
244 /* secs */
245 kProgressAcquireDelay = 0,
246 kProgressReacquireDelay = 5,
247};
13f56ec4
A
248
249static int8_t vc_rotate_matr[4][2][2] = {
250 { { 1, 0 },
251 { 0, 1 } },
252 { { 0, 1 },
253 { -1, 0 } },
254 { { -1, 0 },
255 { 0, -1 } },
256 { { 0, -1 },
257 { 1, 0 } }
258};
259
55e303ae
A
260static int gc_wrap_mode = 1, gc_relative_origin = 0;
261static int gc_charset_select = 0, gc_save_charset_s = 0;
262static int gc_charset[2] = { 0, 0 };
263static int gc_charset_save[2] = { 0, 0 };
264
2d21ac55
A
265static void gc_clear_line(unsigned int xx, unsigned int yy, int which);
266static void gc_clear_screen(unsigned int xx, unsigned int yy, int top,
267 unsigned int bottom, int which);
55e303ae 268static void gc_enable(boolean_t enable);
2d21ac55 269static void gc_hide_cursor(unsigned int xx, unsigned int yy);
55e303ae 270static void gc_initialize(struct vc_info * info);
060df5ea 271static boolean_t gc_is_tab_stop(unsigned int column);
2d21ac55
A
272static void gc_paint_char(unsigned int xx, unsigned int yy, unsigned char ch,
273 int attrs);
55e303ae
A
274static void gc_putchar(char ch);
275static void gc_putc_askcmd(unsigned char ch);
276static void gc_putc_charsetcmd(int charset, unsigned char ch);
277static void gc_putc_charsizecmd(unsigned char ch);
278static void gc_putc_esc(unsigned char ch);
279static void gc_putc_getpars(unsigned char ch);
280static void gc_putc_gotpars(unsigned char ch);
281static void gc_putc_normal(unsigned char ch);
282static void gc_putc_square(unsigned char ch);
55e303ae
A
283static void gc_reset_screen(void);
284static void gc_reset_tabs(void);
285static void gc_reset_vt100(void);
2d21ac55
A
286static void gc_scroll_down(int num, unsigned int top, unsigned int bottom);
287static void gc_scroll_up(int num, unsigned int top, unsigned int bottom);
060df5ea 288static void gc_set_tab_stop(unsigned int column, boolean_t enabled);
2d21ac55 289static void gc_show_cursor(unsigned int xx, unsigned int yy);
55e303ae 290static void gc_update_color(int color, boolean_t fore);
55e303ae
A
291
292static void
2d21ac55 293gc_clear_line(unsigned int xx, unsigned int yy, int which)
55e303ae 294{
2d21ac55 295 unsigned int start, end, i;
55e303ae
A
296
297 /*
298 * This routine runs extremely slowly. I don't think it's
299 * used all that often, except for To end of line. I'll go
300 * back and speed this up when I speed up the whole vc
301 * module. --LK
302 */
303
304 switch (which) {
305 case 0: /* To end of line */
306 start = xx;
307 end = vinfo.v_columns-1;
308 break;
309 case 1: /* To start of line */
310 start = 0;
311 end = xx;
312 break;
313 case 2: /* Whole line */
314 start = 0;
315 end = vinfo.v_columns-1;
316 break;
2d21ac55
A
317 default:
318 return;
55e303ae
A
319 }
320
321 for (i = start; i <= end; i++) {
322 gc_paint_char(i, yy, ' ', ATTR_NONE);
323 }
55e303ae
A
324}
325
326static void
2d21ac55
A
327gc_clear_screen(unsigned int xx, unsigned int yy, int top, unsigned int bottom,
328 int which)
55e303ae 329{
060df5ea 330 if (!gc_buffer_size) return;
0c530ab8 331
55e303ae
A
332 if ( xx < gc_buffer_columns && yy < gc_buffer_rows && bottom <= gc_buffer_rows )
333 {
b0d623f7 334 uint32_t start, end;
55e303ae
A
335
336 switch (which) {
337 case 0: /* To end of screen */
338 start = (yy * gc_buffer_columns) + xx;
339 end = (bottom * gc_buffer_columns) - 1;
340 break;
341 case 1: /* To start of screen */
342 start = (top * gc_buffer_columns);
343 end = (yy * gc_buffer_columns) + xx;
344 break;
345 case 2: /* Whole screen */
346 start = (top * gc_buffer_columns);
347 end = (bottom * gc_buffer_columns) - 1;
348 break;
2d21ac55
A
349 default:
350 start = 0;
351 end = 0;
352 break;
55e303ae
A
353 }
354
2d21ac55
A
355 memset(gc_buffer_attributes + start, ATTR_NONE, end - start + 1);
356 memset(gc_buffer_characters + start, ' ', end - start + 1);
55e303ae
A
357 memset(gc_buffer_colorcodes + start, gc_color_code, end - start + 1);
358 }
359
55e303ae
A
360 gc_ops.clear_screen(xx, yy, top, bottom, which);
361}
362
363static void
364gc_enable( boolean_t enable )
365{
2d21ac55
A
366 unsigned char *buffer_attributes = NULL;
367 unsigned char *buffer_characters = NULL;
368 unsigned char *buffer_colorcodes = NULL;
060df5ea 369 unsigned char *buffer_tab_stops = NULL;
b0d623f7
A
370 uint32_t buffer_columns = 0;
371 uint32_t buffer_rows = 0;
372 uint32_t buffer_size = 0;
55e303ae
A
373 spl_t s;
374
375 if ( enable == FALSE )
376 {
2d21ac55
A
377 // only disable console output if it goes to the graphics console
378 if ( console_is_serial() == FALSE )
379 disableConsoleOutput = TRUE;
55e303ae
A
380 gc_enabled = FALSE;
381 gc_ops.enable(FALSE);
382 }
383
384 s = splhigh( );
2d21ac55 385 VCPUTC_LOCK_LOCK( );
55e303ae
A
386
387 if ( gc_buffer_size )
388 {
389 buffer_attributes = gc_buffer_attributes;
390 buffer_characters = gc_buffer_characters;
391 buffer_colorcodes = gc_buffer_colorcodes;
060df5ea
A
392 buffer_tab_stops = gc_buffer_tab_stops;
393 buffer_columns = gc_buffer_columns;
394 buffer_rows = gc_buffer_rows;
55e303ae
A
395 buffer_size = gc_buffer_size;
396
397 gc_buffer_attributes = NULL;
398 gc_buffer_characters = NULL;
399 gc_buffer_colorcodes = NULL;
060df5ea 400 gc_buffer_tab_stops = NULL;
55e303ae
A
401 gc_buffer_columns = 0;
402 gc_buffer_rows = 0;
403 gc_buffer_size = 0;
404
2d21ac55 405 VCPUTC_LOCK_UNLOCK( );
55e303ae
A
406 splx( s );
407
91447636
A
408 kfree( buffer_attributes, buffer_size );
409 kfree( buffer_characters, buffer_size );
410 kfree( buffer_colorcodes, buffer_size );
060df5ea 411 kfree( buffer_tab_stops, buffer_columns );
55e303ae
A
412 }
413 else
414 {
2d21ac55 415 VCPUTC_LOCK_UNLOCK( );
55e303ae
A
416 splx( s );
417 }
418
419 if ( enable )
420 {
421 if ( vm_initialized )
422 {
423 buffer_columns = vinfo.v_columns;
424 buffer_rows = vinfo.v_rows;
425 buffer_size = buffer_columns * buffer_rows;
426
427 if ( buffer_size )
428 {
429 buffer_attributes = (unsigned char *) kalloc( buffer_size );
430 buffer_characters = (unsigned char *) kalloc( buffer_size );
431 buffer_colorcodes = (unsigned char *) kalloc( buffer_size );
060df5ea 432 buffer_tab_stops = (unsigned char *) kalloc( buffer_columns );
55e303ae
A
433
434 if ( buffer_attributes == NULL ||
435 buffer_characters == NULL ||
060df5ea
A
436 buffer_colorcodes == NULL ||
437 buffer_tab_stops == NULL )
55e303ae 438 {
91447636
A
439 if ( buffer_attributes ) kfree( buffer_attributes, buffer_size );
440 if ( buffer_characters ) kfree( buffer_characters, buffer_size );
441 if ( buffer_colorcodes ) kfree( buffer_colorcodes, buffer_size );
060df5ea 442 if ( buffer_tab_stops ) kfree( buffer_tab_stops, buffer_columns );
55e303ae 443
3e170ce0
A
444 buffer_attributes = NULL;
445 buffer_characters = NULL;
446 buffer_colorcodes = NULL;
447 buffer_tab_stops = NULL;
55e303ae
A
448 buffer_columns = 0;
449 buffer_rows = 0;
450 buffer_size = 0;
451 }
452 else
453 {
2d21ac55
A
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 );
060df5ea 457 memset( buffer_tab_stops, 0, buffer_columns );
55e303ae
A
458 }
459 }
460 }
461
462 s = splhigh( );
2d21ac55 463 VCPUTC_LOCK_LOCK( );
55e303ae
A
464
465 gc_buffer_attributes = buffer_attributes;
466 gc_buffer_characters = buffer_characters;
467 gc_buffer_colorcodes = buffer_colorcodes;
060df5ea 468 gc_buffer_tab_stops = buffer_tab_stops;
55e303ae
A
469 gc_buffer_columns = buffer_columns;
470 gc_buffer_rows = buffer_rows;
471 gc_buffer_size = buffer_size;
472
2d21ac55
A
473 gc_reset_screen();
474
475 VCPUTC_LOCK_UNLOCK( );
55e303ae
A
476 splx( s );
477
2d21ac55
A
478 gc_ops.clear_screen(gc_x, gc_y, 0, vinfo.v_rows, 2);
479 gc_ops.show_cursor(gc_x, gc_y);
55e303ae
A
480
481 gc_ops.enable(TRUE);
482 gc_enabled = TRUE;
483 disableConsoleOutput = FALSE;
484 }
485}
486
487static void
2d21ac55 488gc_hide_cursor(unsigned int xx, unsigned int yy)
55e303ae 489{
55e303ae
A
490 if ( xx < gc_buffer_columns && yy < gc_buffer_rows )
491 {
b0d623f7 492 uint32_t index = (yy * gc_buffer_columns) + xx;
55e303ae
A
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
55e303ae
A
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 {
55e303ae
A
508 gc_ops.hide_cursor(xx, yy);
509 }
510}
511
512static void
513gc_initialize(struct vc_info * info)
514{
515 if ( gc_initialized == FALSE )
516 {
517 /* Init our lock */
2d21ac55 518 VCPUTC_LOCK_INIT();
55e303ae
A
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
529static void
2d21ac55 530gc_paint_char(unsigned int xx, unsigned int yy, unsigned char ch, int attrs)
55e303ae 531{
55e303ae
A
532 if ( xx < gc_buffer_columns && yy < gc_buffer_rows )
533 {
b0d623f7 534 uint32_t index = (yy * gc_buffer_columns) + xx;
55e303ae
A
535
536 gc_buffer_attributes[index] = attrs;
537 gc_buffer_characters[index] = ch;
538 gc_buffer_colorcodes[index] = gc_color_code;
539 }
540
55e303ae
A
541 gc_ops.paint_char(xx, yy, ch, attrs, 0, 0);
542}
543
544static void
545gc_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) {
2d21ac55
A
582 if (0 == vinfo.v_columns)
583 gc_x = 0;
584 else
585 gc_x = vinfo.v_columns - 1;
55e303ae
A
586 }
587 if (gc_y >= vinfo.v_rows) {
2d21ac55
A
588 if (0 == vinfo.v_rows)
589 gc_y = 0;
590 else
591 gc_y = vinfo.v_rows - 1;
55e303ae 592 }
55e303ae
A
593}
594
595static void
596gc_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
617static void
618gc_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
636static void
637gc_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 {
2d21ac55 649 unsigned int xx, yy;
55e303ae
A
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
659static void
660gc_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 */
060df5ea 684 gc_set_tab_stop(gc_x, TRUE);
55e303ae
A
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
733static void
734gc_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
758static void
759gc_putc_gotpars(unsigned char ch)
760{
2d21ac55 761 unsigned int i;
55e303ae
A
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 */
2d21ac55 788 if (gc_par[0] > gc_x)
55e303ae 789 gc_x = 0;
2d21ac55
A
790 else if (gc_par[0])
791 gc_x -= gc_par[0];
792 else if (gc_x)
793 --gc_x;
55e303ae
A
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) {
55e303ae
A
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 {
55e303ae 823 for (i = 0; i <= vinfo.v_columns; i++)
060df5ea 824 gc_set_tab_stop(i, FALSE);
55e303ae
A
825 }
826 break;
827 case 0:
060df5ea 828 gc_set_tab_stop(gc_x, FALSE);
55e303ae
A
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;
55e303ae
A
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
892static void
893gc_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 */
060df5ea
A
908 if (gc_buffer_tab_stops) while (gc_x < vinfo.v_columns && !gc_is_tab_stop(++gc_x));
909
55e303ae
A
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
966static void
967gc_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
55e303ae
A
982static void
983gc_reset_screen(void)
984{
55e303ae
A
985 gc_reset_vt100();
986 gc_x = gc_y = 0;
55e303ae
A
987}
988
989static void
990gc_reset_tabs(void)
991{
2d21ac55 992 unsigned int i;
060df5ea
A
993
994 if (!gc_buffer_tab_stops) return;
55e303ae 995
060df5ea
A
996 for (i = 0; i < vinfo.v_columns; i++) {
997 gc_buffer_tab_stops[i] = ((i % 8) == 0);
55e303ae
A
998 }
999
1000}
1001
060df5ea
A
1002static void
1003gc_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
1010static 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
55e303ae
A
1020static void
1021gc_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
1035static void
2d21ac55 1036gc_scroll_down(int num, unsigned int top, unsigned int bottom)
55e303ae 1037{
060df5ea 1038 if (!gc_buffer_size) return;
0c530ab8 1039
55e303ae
A
1040 if ( bottom <= gc_buffer_rows )
1041 {
1042 unsigned char colorcodesave = gc_color_code;
b0d623f7
A
1043 uint32_t column, row;
1044 uint32_t index, jump;
55e303ae
A
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
2d21ac55
A
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 }
55e303ae
A
1133 }
1134 else
1135 {
55e303ae 1136 gc_ops.scroll_down(num, top, bottom);
55e303ae 1137
2d21ac55 1138 /* Now set the freed up lines to the background colour */
55e303ae 1139
2d21ac55
A
1140 gc_clear_screen(vinfo.v_columns - 1, top + num - 1, top, bottom, 1);
1141 }
55e303ae
A
1142}
1143
1144static void
2d21ac55 1145gc_scroll_up(int num, unsigned int top, unsigned int bottom)
55e303ae 1146{
060df5ea 1147 if (!gc_buffer_size) return;
0c530ab8 1148
55e303ae
A
1149 if ( bottom <= gc_buffer_rows )
1150 {
1151 unsigned char colorcodesave = gc_color_code;
b0d623f7
A
1152 uint32_t column, row;
1153 uint32_t index, jump;
55e303ae
A
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];
55e303ae
A
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
2d21ac55
A
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 }
55e303ae
A
1242 }
1243 else
1244 {
55e303ae 1245 gc_ops.scroll_up(num, top, bottom);
55e303ae 1246
2d21ac55 1247 /* Now set the freed up lines to the background colour */
55e303ae 1248
2d21ac55
A
1249 gc_clear_screen(0, bottom - num, top, bottom, 0);
1250 }
55e303ae
A
1251}
1252
1253static void
2d21ac55 1254gc_show_cursor(unsigned int xx, unsigned int yy)
55e303ae 1255{
55e303ae
A
1256 if ( xx < gc_buffer_columns && yy < gc_buffer_rows )
1257 {
b0d623f7 1258 uint32_t index = (yy * gc_buffer_columns) + xx;
55e303ae
A
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
55e303ae
A
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 {
55e303ae
A
1274 gc_ops.show_cursor(xx, yy);
1275 }
1276}
1277
1278static void
1279gc_update_color(int color, boolean_t fore)
1280{
316670eb
A
1281 assert(gc_ops.update_color);
1282
55e303ae
A
1283 gc_color_code = COLOR_CODE_SET(gc_color_code, color, fore);
1284 gc_ops.update_color(color, fore);
1285}
1286
2d21ac55
A
1287void
1288vcputc(__unused int l, __unused int u, int c)
55e303ae 1289{
6d2010ae 1290 if ( gc_initialized && ( gc_enabled || debug_mode ) )
2d21ac55
A
1291 {
1292 spl_t s;
1293
1294 s = splhigh();
060df5ea
A
1295#if defined(__i386__) || defined(__x86_64__)
1296 x86_filter_TLB_coherency_interrupts(TRUE);
1297#endif
2d21ac55 1298 VCPUTC_LOCK_LOCK();
060df5ea
A
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 }
2d21ac55 1305 VCPUTC_LOCK_UNLOCK();
060df5ea
A
1306#if defined(__i386__) || defined(__x86_64__)
1307 x86_filter_TLB_coherency_interrupts(FALSE);
1308#endif
2d21ac55
A
1309 splx(s);
1310 }
55e303ae
A
1311}
1312
1313/*
1314 * Video Console (Back-End)
1315 * ------------------------
1316 */
1317
1318/*
1319 * For the color support (Michel Pollet)
1320 */
1321static unsigned char vc_color_index_table[33] =
1322 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
b0d623f7
A
1323 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 2 };
1324
1325static 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 */
55e303ae
A
1335};
1336
b0d623f7
A
1337static uint32_t vc_color_fore = 0;
1338static uint32_t vc_color_back = 0;
55e303ae
A
1339
1340/*
1341 * New Rendering code from Michel Pollet
1342 */
1343
1344/* Rendered Font Buffer */
1345static unsigned char *vc_rendered_font = NULL;
1346
1347/* Rendered Font Size */
b0d623f7 1348static uint32_t vc_rendered_font_size = 0;
55e303ae
A
1349
1350/* Size of a character in the table (bytes) */
1351static int vc_rendered_char_size = 0;
1352
1353#define REN_MAX_DEPTH 32
1354static unsigned char vc_rendered_char[ISO_CHAR_HEIGHT * ((REN_MAX_DEPTH / 8) * ISO_CHAR_WIDTH)];
1355
fe8ab488
A
1356static void
1357internal_set_progressmeter(int new_value);
1358static void
1359internal_enable_progressmeter(int new_value);
1360
1361enum
1362{
1363 kProgressMeterOff = FALSE,
1364 kProgressMeterUser = TRUE,
1365 kProgressMeterKernel = 3,
1366};
1367enum
1368{
1369 kProgressMeterMax = 1024,
1370 kProgressMeterEnd = 512,
1371};
1372
1373
1374static boolean_t vc_progress_white =
1375#ifdef CONFIG_VC_PROGRESS_WHITE
1376 TRUE;
1377#else /* !CONFIG_VC_PROGRESS_WHITE */
1378 FALSE;
1379#endif /* !CONFIG_VC_PROGRESS_WHITE */
1380
1381static int vc_acquire_delay = kProgressAcquireDelay;
1382
55e303ae 1383static void
2d21ac55
A
1384vc_clear_screen(unsigned int xx, unsigned int yy, unsigned int scrreg_top,
1385 unsigned int scrreg_bottom, int which)
55e303ae 1386{
b0d623f7 1387 uint32_t *p, *endp, *row;
55e303ae
A
1388 int linelongs, col;
1389 int rowline, rowlongs;
1390
1391 if(!vinfo.v_depth)
1392 return;
1393
1394 linelongs = vinfo.v_rowbytes * (ISO_CHAR_HEIGHT >> 2);
1395 rowline = vinfo.v_rowscanbytes >> 2;
1396 rowlongs = vinfo.v_rowbytes >> 2;
1397
b0d623f7
A
1398 p = (uint32_t*) vinfo.v_baseaddr;
1399 endp = (uint32_t*) vinfo.v_baseaddr;
55e303ae
A
1400
1401 switch (which) {
1402 case 0: /* To end of screen */
1403 gc_clear_line(xx, yy, 0);
1404 if (yy < scrreg_bottom - 1) {
1405 p += (yy + 1) * linelongs;
1406 endp += scrreg_bottom * linelongs;
1407 }
1408 break;
1409 case 1: /* To start of screen */
1410 gc_clear_line(xx, yy, 1);
1411 if (yy > scrreg_top) {
1412 p += scrreg_top * linelongs;
1413 endp += yy * linelongs;
1414 }
1415 break;
1416 case 2: /* Whole screen */
1417 p += scrreg_top * linelongs;
1418 if (scrreg_bottom == vinfo.v_rows) {
1419 endp += rowlongs * vinfo.v_height;
1420 } else {
1421 endp += scrreg_bottom * linelongs;
1422 }
1423 break;
1424 }
1425
1426 for (row = p ; row < endp ; row += rowlongs) {
1427 for (col = 0; col < rowline; col++)
1428 *(row+col) = vc_color_back;
1429 }
1430}
1431
55e303ae 1432static void
2d21ac55 1433vc_render_char(unsigned char ch, unsigned char *renderptr, short newdepth)
55e303ae 1434{
2d21ac55
A
1435 union {
1436 unsigned char *charptr;
1437 unsigned short *shortptr;
b0d623f7 1438 uint32_t *longptr;
2d21ac55
A
1439 } current; /* current place in rendered font, multiple types. */
1440 unsigned char *theChar; /* current char in iso_font */
1441 int line;
55e303ae 1442
2d21ac55
A
1443 current.charptr = renderptr;
1444 theChar = iso_font + (ch * ISO_CHAR_HEIGHT);
1445
1446 for (line = 0; line < ISO_CHAR_HEIGHT; line++) {
1447 unsigned char mask = 1;
1448 do {
1449 switch (newdepth) {
1450 case 8:
1451 *current.charptr++ = (*theChar & mask) ? 0xFF : 0;
1452 break;
1453 case 16:
1454 *current.shortptr++ = (*theChar & mask) ? 0xFFFF : 0;
1455 break;
1456
b0d623f7 1457 case 30:
2d21ac55
A
1458 case 32:
1459 *current.longptr++ = (*theChar & mask) ? 0xFFFFFFFF : 0;
1460 break;
1461 }
1462 mask <<= 1;
1463 } while (mask); /* while the single bit drops to the right */
1464 theChar++;
55e303ae
A
1465 }
1466}
1467
1468static void
2d21ac55
A
1469vc_paint_char_8(unsigned int xx, unsigned int yy, unsigned char ch, int attrs,
1470 __unused unsigned char ch_previous, __unused int attrs_previous)
55e303ae 1471{
b0d623f7
A
1472 uint32_t *theChar;
1473 uint32_t *where;
55e303ae
A
1474 int i;
1475
1476 if (vc_rendered_font) {
b0d623f7 1477 theChar = (uint32_t*)(vc_rendered_font + (ch * vc_rendered_char_size));
55e303ae
A
1478 } else {
1479 vc_render_char(ch, vc_rendered_char, 8);
b0d623f7 1480 theChar = (uint32_t*)(vc_rendered_char);
55e303ae 1481 }
b0d623f7 1482 where = (uint32_t*)(vinfo.v_baseaddr +
55e303ae
A
1483 (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) +
1484 (xx * ISO_CHAR_WIDTH));
1485
1486 if (!attrs) for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* No attr? FLY !*/
b0d623f7 1487 uint32_t *store = where;
55e303ae
A
1488 int x;
1489 for (x = 0; x < 2; x++) {
b0d623f7 1490 uint32_t val = *theChar++;
55e303ae
A
1491 val = (vc_color_back & ~val) | (vc_color_fore & val);
1492 *store++ = val;
1493 }
1494
b0d623f7 1495 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
55e303ae 1496 } else for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* a little slower */
b0d623f7 1497 uint32_t *store = where, lastpixel = 0;
55e303ae
A
1498 int x;
1499 for (x = 0 ; x < 2; x++) {
b0d623f7 1500 uint32_t val = *theChar++, save = val;
55e303ae
A
1501 if (attrs & ATTR_BOLD) { /* bold support */
1502 if (lastpixel && !(save & 0xFF000000))
1503 val |= 0xff000000;
1504 if ((save & 0xFFFF0000) == 0xFF000000)
1505 val |= 0x00FF0000;
1506 if ((save & 0x00FFFF00) == 0x00FF0000)
1507 val |= 0x0000FF00;
1508 if ((save & 0x0000FFFF) == 0x0000FF00)
1509 val |= 0x000000FF;
1510 }
1511 if (attrs & ATTR_REVERSE) val = ~val;
1512 if (attrs & ATTR_UNDER && i == ISO_CHAR_HEIGHT-1) val = ~val;
1513
1514 val = (vc_color_back & ~val) | (vc_color_fore & val);
1515 *store++ = val;
1516 lastpixel = save & 0xff;
1517 }
1518
b0d623f7 1519 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
55e303ae
A
1520 }
1521
1522}
1523
1524static void
2d21ac55
A
1525vc_paint_char_16(unsigned int xx, unsigned int yy, unsigned char ch, int attrs,
1526 __unused unsigned char ch_previous,
1527 __unused int attrs_previous)
55e303ae 1528{
b0d623f7
A
1529 uint32_t *theChar;
1530 uint32_t *where;
55e303ae
A
1531 int i;
1532
1533 if (vc_rendered_font) {
b0d623f7 1534 theChar = (uint32_t*)(vc_rendered_font + (ch * vc_rendered_char_size));
55e303ae
A
1535 } else {
1536 vc_render_char(ch, vc_rendered_char, 16);
b0d623f7 1537 theChar = (uint32_t*)(vc_rendered_char);
55e303ae 1538 }
b0d623f7 1539 where = (uint32_t*)(vinfo.v_baseaddr +
55e303ae
A
1540 (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) +
1541 (xx * ISO_CHAR_WIDTH * 2));
1542
1543 if (!attrs) for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* No attrs ? FLY ! */
b0d623f7 1544 uint32_t *store = where;
55e303ae
A
1545 int x;
1546 for (x = 0; x < 4; x++) {
b0d623f7 1547 uint32_t val = *theChar++;
55e303ae
A
1548 val = (vc_color_back & ~val) | (vc_color_fore & val);
1549 *store++ = val;
1550 }
1551
b0d623f7 1552 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
55e303ae 1553 } else for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* a little bit slower */
b0d623f7 1554 uint32_t *store = where, lastpixel = 0;
55e303ae
A
1555 int x;
1556 for (x = 0 ; x < 4; x++) {
b0d623f7 1557 uint32_t val = *theChar++, save = val;
55e303ae
A
1558 if (attrs & ATTR_BOLD) { /* bold support */
1559 if (save == 0xFFFF0000) val |= 0xFFFF;
1560 else if (lastpixel && !(save & 0xFFFF0000))
1561 val |= 0xFFFF0000;
1562 }
1563 if (attrs & ATTR_REVERSE) val = ~val;
1564 if (attrs & ATTR_UNDER && i == ISO_CHAR_HEIGHT-1) val = ~val;
1565
1566 val = (vc_color_back & ~val) | (vc_color_fore & val);
1567
1568 *store++ = val;
1569 lastpixel = save & 0x7fff;
1570 }
1571
b0d623f7 1572 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
55e303ae
A
1573 }
1574
1575}
1576
1577static void
2d21ac55
A
1578vc_paint_char_32(unsigned int xx, unsigned int yy, unsigned char ch, int attrs,
1579 unsigned char ch_previous, int attrs_previous)
55e303ae 1580{
b0d623f7
A
1581 uint32_t *theChar;
1582 uint32_t *theCharPrevious;
1583 uint32_t *where;
55e303ae
A
1584 int i;
1585
1586 if (vc_rendered_font) {
b0d623f7
A
1587 theChar = (uint32_t*)(vc_rendered_font + (ch * vc_rendered_char_size));
1588 theCharPrevious = (uint32_t*)(vc_rendered_font + (ch_previous * vc_rendered_char_size));
55e303ae
A
1589 } else {
1590 vc_render_char(ch, vc_rendered_char, 32);
b0d623f7 1591 theChar = (uint32_t*)(vc_rendered_char);
55e303ae
A
1592 theCharPrevious = NULL;
1593 }
1594 if (!ch_previous) {
1595 theCharPrevious = NULL;
1596 }
1597 if (attrs_previous) {
1598 theCharPrevious = NULL;
1599 }
b0d623f7 1600 where = (uint32_t*)(vinfo.v_baseaddr +
55e303ae
A
1601 (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) +
1602 (xx * ISO_CHAR_WIDTH * 4));
1603
1604 if (!attrs) for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* No attrs ? FLY ! */
b0d623f7 1605 uint32_t *store = where;
55e303ae
A
1606 int x;
1607 for (x = 0; x < 8; x++) {
b0d623f7 1608 uint32_t val = *theChar++;
55e303ae
A
1609 if (theCharPrevious == NULL || val != *theCharPrevious++ ) {
1610 val = (vc_color_back & ~val) | (vc_color_fore & val);
1611 *store++ = val;
1612 } else {
1613 store++;
1614 }
1615 }
1616
b0d623f7 1617 where = (uint32_t *)(((unsigned char*)where)+vinfo.v_rowbytes);
55e303ae 1618 } else for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* a little slower */
b0d623f7 1619 uint32_t *store = where, lastpixel = 0;
55e303ae
A
1620 int x;
1621 for (x = 0 ; x < 8; x++) {
b0d623f7 1622 uint32_t val = *theChar++, save = val;
55e303ae
A
1623 if (attrs & ATTR_BOLD) { /* bold support */
1624 if (lastpixel && !save)
1625 val = 0xFFFFFFFF;
1626 }
1627 if (attrs & ATTR_REVERSE) val = ~val;
1628 if (attrs & ATTR_UNDER && i == ISO_CHAR_HEIGHT-1) val = ~val;
1629
1630 val = (vc_color_back & ~val) | (vc_color_fore & val);
1631 *store++ = val;
1632 lastpixel = save;
1633 }
1634
b0d623f7 1635 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
55e303ae
A
1636 }
1637
1638}
1639
1640static void
2d21ac55
A
1641vc_paint_char(unsigned int xx, unsigned int yy, unsigned char ch, int attrs,
1642 unsigned char ch_previous, int attrs_previous)
55e303ae 1643{
2d21ac55
A
1644 if(!vinfo.v_depth)
1645 return;
55e303ae 1646
2d21ac55
A
1647 switch(vinfo.v_depth) {
1648 case 8:
1649 vc_paint_char_8(xx, yy, ch, attrs, ch_previous, attrs_previous);
1650 break;
1651 case 16:
1652 vc_paint_char_16(xx, yy, ch, attrs, ch_previous,
1653 attrs_previous);
1654 break;
b0d623f7 1655 case 30:
2d21ac55
A
1656 case 32:
1657 vc_paint_char_32(xx, yy, ch, attrs, ch_previous,
1658 attrs_previous);
1659 break;
55e303ae
A
1660 }
1661}
1662
1663static void
1664vc_render_font(short newdepth)
1665{
1666 static short olddepth = 0;
1667
1668 int charindex; /* index in ISO font */
2d21ac55 1669 unsigned char *rendered_font;
b0d623f7 1670 unsigned int rendered_font_size;
2d21ac55
A
1671 int rendered_char_size;
1672 spl_t s;
55e303ae
A
1673
1674 if (vm_initialized == FALSE) {
1675 return; /* nothing to do */
1676 }
1677 if (olddepth == newdepth && vc_rendered_font) {
1678 return; /* nothing to do */
1679 }
2d21ac55
A
1680
1681 s = splhigh();
1682 VCPUTC_LOCK_LOCK();
1683
1684 rendered_font = vc_rendered_font;
1685 rendered_font_size = vc_rendered_font_size;
1686 rendered_char_size = vc_rendered_char_size;
1687
1688 vc_rendered_font = NULL;
1689 vc_rendered_font_size = 0;
1690 vc_rendered_char_size = 0;
1691
1692 VCPUTC_LOCK_UNLOCK();
1693 splx(s);
1694
1695 if (rendered_font) {
1696 kfree(rendered_font, rendered_font_size);
1697 rendered_font = NULL;
55e303ae
A
1698 }
1699
2d21ac55 1700 if (newdepth) {
b0d623f7 1701 rendered_char_size = ISO_CHAR_HEIGHT * (((newdepth + 7) / 8) * ISO_CHAR_WIDTH);
2d21ac55
A
1702 rendered_font_size = (ISO_CHAR_MAX-ISO_CHAR_MIN+1) * rendered_char_size;
1703 rendered_font = (unsigned char *) kalloc(rendered_font_size);
1704 }
55e303ae 1705
2d21ac55 1706 if (rendered_font == NULL) {
55e303ae
A
1707 return;
1708 }
1709
1710 for (charindex = ISO_CHAR_MIN; charindex <= ISO_CHAR_MAX; charindex++) {
2d21ac55 1711 vc_render_char(charindex, rendered_font + (charindex * rendered_char_size), newdepth);
55e303ae
A
1712 }
1713
1714 olddepth = newdepth;
2d21ac55
A
1715
1716 s = splhigh();
1717 VCPUTC_LOCK_LOCK();
1718
1719 vc_rendered_font = rendered_font;
1720 vc_rendered_font_size = rendered_font_size;
1721 vc_rendered_char_size = rendered_char_size;
1722
1723 VCPUTC_LOCK_UNLOCK();
1724 splx(s);
55e303ae
A
1725}
1726
1727static void
2d21ac55
A
1728vc_enable(boolean_t enable)
1729{
1730 vc_render_font(enable ? vinfo.v_depth : 0);
1731}
1732
1733static void
1734vc_reverse_cursor(unsigned int xx, unsigned int yy)
55e303ae 1735{
b0d623f7 1736 uint32_t *where;
55e303ae
A
1737 int line, col;
1738
1739 if(!vinfo.v_depth)
1740 return;
1741
b0d623f7 1742 where = (uint32_t*)(vinfo.v_baseaddr +
55e303ae
A
1743 (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) +
1744 (xx /** ISO_CHAR_WIDTH*/ * vinfo.v_depth));
1745 for (line = 0; line < ISO_CHAR_HEIGHT; line++) {
1746 switch (vinfo.v_depth) {
1747 case 8:
1748 where[0] = ~where[0];
1749 where[1] = ~where[1];
1750 break;
1751 case 16:
1752 for (col = 0; col < 4; col++)
1753 where[col] = ~where[col];
1754 break;
1755 case 32:
1756 for (col = 0; col < 8; col++)
1757 where[col] = ~where[col];
1758 break;
1759 }
b0d623f7 1760 where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes);
55e303ae
A
1761 }
1762}
1763
1764static void
2d21ac55 1765vc_scroll_down(int num, unsigned int scrreg_top, unsigned int scrreg_bottom)
55e303ae 1766{
b0d623f7 1767 uint32_t *from, *to, linelongs, i, line, rowline, rowscanline;
55e303ae
A
1768
1769 if(!vinfo.v_depth)
1770 return;
1771
1772 linelongs = vinfo.v_rowbytes * (ISO_CHAR_HEIGHT >> 2);
1773 rowline = vinfo.v_rowbytes >> 2;
1774 rowscanline = vinfo.v_rowscanbytes >> 2;
1775
b0d623f7 1776 to = (uint32_t *) vinfo.v_baseaddr + (linelongs * scrreg_bottom)
55e303ae
A
1777 - (rowline - rowscanline);
1778 from = to - (linelongs * num); /* handle multiple line scroll (Michel Pollet) */
1779
1780 i = (scrreg_bottom - scrreg_top) - num;
1781
1782 while (i-- > 0) {
1783 for (line = 0; line < ISO_CHAR_HEIGHT; line++) {
1784 /*
1785 * Only copy what is displayed
1786 */
b0d623f7
A
1787 video_scroll_down(from,
1788 (from-(vinfo.v_rowscanbytes >> 2)),
1789 to);
55e303ae
A
1790
1791 from -= rowline;
1792 to -= rowline;
1793 }
1794 }
1795}
1796
1797static void
2d21ac55 1798vc_scroll_up(int num, unsigned int scrreg_top, unsigned int scrreg_bottom)
55e303ae 1799{
b0d623f7 1800 uint32_t *from, *to, linelongs, i, line, rowline, rowscanline;
55e303ae
A
1801
1802 if(!vinfo.v_depth)
1803 return;
1804
1805 linelongs = vinfo.v_rowbytes * (ISO_CHAR_HEIGHT >> 2);
1806 rowline = vinfo.v_rowbytes >> 2;
1807 rowscanline = vinfo.v_rowscanbytes >> 2;
1808
b0d623f7 1809 to = (uint32_t *) vinfo.v_baseaddr + (scrreg_top * linelongs);
55e303ae
A
1810 from = to + (linelongs * num); /* handle multiple line scroll (Michel Pollet) */
1811
1812 i = (scrreg_bottom - scrreg_top) - num;
1813
1814 while (i-- > 0) {
1815 for (line = 0; line < ISO_CHAR_HEIGHT; line++) {
1816 /*
1817 * Only copy what is displayed
1818 */
b0d623f7
A
1819 video_scroll_up(from,
1820 (from+(vinfo.v_rowscanbytes >> 2)),
1821 to);
55e303ae
A
1822
1823 from += rowline;
1824 to += rowline;
1825 }
1826 }
1827}
1828
1829static void
1830vc_update_color(int color, boolean_t fore)
1831{
1832 if (!vinfo.v_depth)
1833 return;
1834 if (fore) {
1835 vc_color_fore = vc_colors[color][vc_color_index_table[vinfo.v_depth]];
1836 } else {
1837 vc_color_back = vc_colors[color][vc_color_index_table[vinfo.v_depth]];
1838 }
1839}
1840
1841/*
1842 * Video Console (Back-End): Icon Control
1843 * --------------------------------------
1844 */
1845
55e303ae 1846static vc_progress_element * vc_progress;
fe8ab488
A
1847enum { kMaxProgressData = 3 };
1848static const unsigned char * vc_progress_data[kMaxProgressData];
55e303ae
A
1849static const unsigned char * vc_progress_alpha;
1850static boolean_t vc_progress_enable;
1851static const unsigned char * vc_clut;
1852static const unsigned char * vc_clut8;
1853static unsigned char vc_revclut8[256];
91447636 1854static uint32_t vc_progress_interval;
060df5ea 1855static uint32_t vc_progress_count;
13f56ec4 1856static uint32_t vc_progress_angle;
91447636
A
1857static uint64_t vc_progress_deadline;
1858static thread_call_data_t vc_progress_call;
55e303ae 1859static boolean_t vc_needsave;
91447636 1860static void * vc_saveunder;
55e303ae 1861static vm_size_t vc_saveunder_len;
fe8ab488 1862static int8_t vc_uiscale = 1;
3e170ce0 1863int vc_user_options;
55e303ae
A
1864decl_simple_lock_data(,vc_progress_lock)
1865
fe8ab488
A
1866static int vc_progress_withmeter = 3;
1867int vc_progressmeter_enable;
1868static int vc_progressmeter_drawn;
1869int vc_progressmeter_value;
1870static uint32_t vc_progressmeter_count;
3e170ce0
A
1871static uint32_t vc_progress_meter_start;
1872static uint32_t vc_progress_meter_end;
fe8ab488
A
1873static uint64_t vc_progressmeter_interval;
1874static uint64_t vc_progressmeter_deadline;
1875static thread_call_data_t vc_progressmeter_call;
1876static void * vc_progressmeter_backbuffer;
1877static boolean_t vc_progressmeter_hold;
1878static uint32_t vc_progressmeter_diskspeed = 256;
1879
3e170ce0 1880
b0d623f7 1881enum {
13f56ec4
A
1882 kSave = 0x10,
1883 kDataIndexed = 0x20,
1884 kDataAlpha = 0x40,
1885 kDataBack = 0x80,
1886 kDataRotate = 0x03,
1887 kDataRotate0 = 0,
1888 kDataRotate90 = 1,
1889 kDataRotate180 = 2,
1890 kDataRotate270 = 3
b0d623f7
A
1891};
1892
1893static void vc_blit_rect(int x, int y, int bx,
1894 int width, int height,
1895 int sourceRow, int backRow,
1896 const unsigned char * dataPtr,
1897 void * backBuffer,
1898 unsigned int flags);
1899static void vc_blit_rect_8(int x, int y, int bx,
1900 int width, int height,
1901 int sourceRow, int backRow,
1902 const unsigned char * dataPtr,
1903 unsigned char * backBuffer,
1904 unsigned int flags);
1905static void vc_blit_rect_16(int x, int y, int bx,
1906 int width, int height,
1907 int sourceRow, int backRow,
1908 const unsigned char * dataPtr,
1909 unsigned short * backBuffer,
1910 unsigned int flags);
1911static void vc_blit_rect_32(int x, int y, int bx,
1912 int width, int height,
1913 int sourceRow, int backRow,
1914 const unsigned char * dataPtr,
1915 unsigned int * backBuffer,
1916 unsigned int flags);
1917static void vc_blit_rect_30(int x, int y, int bx,
1918 int width, int height,
1919 int sourceRow, int backRow,
1920 const unsigned char * dataPtr,
1921 unsigned int * backBuffer,
1922 unsigned int flags);
91447636 1923static void vc_progress_task( void * arg0, void * arg );
fe8ab488 1924static void vc_progressmeter_task( void * arg0, void * arg );
55e303ae 1925
b0d623f7
A
1926static void vc_blit_rect(int x, int y, int bx,
1927 int width, int height,
1928 int sourceRow, int backRow,
1929 const unsigned char * dataPtr,
1930 void * backBuffer,
1931 unsigned int flags)
55e303ae 1932{
3e170ce0
A
1933 if (!vinfo.v_depth) return;
1934 if (((unsigned int)(x + width)) > vinfo.v_width) return;
1935 if (((unsigned int)(y + height)) > vinfo.v_height) return;
55e303ae
A
1936
1937 switch( vinfo.v_depth) {
1938 case 8:
1939 if( vc_clut8 == vc_clut)
b0d623f7 1940 vc_blit_rect_8( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned char *) backBuffer, flags );
55e303ae
A
1941 break;
1942 case 16:
b0d623f7 1943 vc_blit_rect_16( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned short *) backBuffer, flags );
55e303ae
A
1944 break;
1945 case 32:
b0d623f7
A
1946 vc_blit_rect_32( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned int *) backBuffer, flags );
1947 break;
1948 case 30:
1949 vc_blit_rect_30( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned int *) backBuffer, flags );
55e303ae
A
1950 break;
1951 }
1952}
1953
2d21ac55 1954static void
b0d623f7
A
1955vc_blit_rect_8(int x, int y, __unused int bx,
1956 int width, int height,
1957 int sourceRow, __unused int backRow,
1958 const unsigned char * dataPtr,
1959 __unused unsigned char * backBuffer,
1960 __unused unsigned int flags)
55e303ae 1961{
b0d623f7 1962 volatile unsigned short * dst;
55e303ae 1963 int line, col;
b0d623f7 1964 unsigned int data = 0, out = 0;
13f56ec4
A
1965 int sx, sy, a, b, c, d;
1966 int scale = 0x10000;
1967
1968 a = vc_rotate_matr[kDataRotate & flags][0][0] * scale;
1969 b = vc_rotate_matr[kDataRotate & flags][0][1] * scale;
1970 c = vc_rotate_matr[kDataRotate & flags][1][0] * scale;
1971 d = vc_rotate_matr[kDataRotate & flags][1][1] * scale;
1972 sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0;
1973 sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0;
1974
1975 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr;
1976 else if (1 == sourceRow) a = 0;
b0d623f7 1977
b0d623f7
A
1978 dst = (volatile unsigned short *) (vinfo.v_baseaddr +
1979 (y * vinfo.v_rowbytes) +
1980 (x * 4));
1981
1982 for( line = 0; line < height; line++)
1983 {
1984 for( col = 0; col < width; col++)
1985 {
13f56ec4
A
1986 if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16)
1987 + sourceRow * (((sy + (col * c) + (line * d)) >> 16))];
b0d623f7
A
1988 if (kDataAlpha & flags)
1989 out = vc_revclut8[data];
1990 else
1991 out = data;
1992 *(dst + col) = out;
1993 }
1994 dst = (volatile unsigned short *) (((volatile char*)dst) + vinfo.v_rowbytes);
55e303ae
A
1995 }
1996}
1997
2d21ac55
A
1998/* For ARM, 16-bit is 565 (RGB); it is 1555 (XRGB) on other platforms */
1999
2000#define CLUT_MASK_R 0xf8
2001#define CLUT_MASK_G 0xf8
2002#define CLUT_MASK_B 0xf8
2003#define CLUT_SHIFT_R << 7
2004#define CLUT_SHIFT_G << 2
2005#define CLUT_SHIFT_B >> 3
2006#define MASK_R 0x7c00
2007#define MASK_G 0x03e0
2008#define MASK_B 0x001f
2009#define MASK_R_8 0x3fc00
2010#define MASK_G_8 0x01fe0
2011#define MASK_B_8 0x000ff
2012
b0d623f7
A
2013static void vc_blit_rect_16( int x, int y, int bx,
2014 int width, int height,
2015 int sourceRow, int backRow,
2016 const unsigned char * dataPtr,
2017 unsigned short * backPtr,
2018 unsigned int flags)
55e303ae
A
2019{
2020 volatile unsigned short * dst;
2021 int line, col;
b0d623f7 2022 unsigned int data = 0, out = 0, back = 0;
13f56ec4
A
2023 int sx, sy, a, b, c, d;
2024 int scale = 0x10000;
2025
2026 a = vc_rotate_matr[kDataRotate & flags][0][0] * scale;
2027 b = vc_rotate_matr[kDataRotate & flags][0][1] * scale;
2028 c = vc_rotate_matr[kDataRotate & flags][1][0] * scale;
2029 d = vc_rotate_matr[kDataRotate & flags][1][1] * scale;
2030 sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0;
2031 sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0;
2032
2033 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr;
2034 else if (1 == sourceRow) a = 0;
55e303ae 2035
b0d623f7
A
2036 if (backPtr)
2037 backPtr += bx;
b0d623f7 2038 dst = (volatile unsigned short *) (vinfo.v_baseaddr +
55e303ae
A
2039 (y * vinfo.v_rowbytes) +
2040 (x * 2));
2041
b0d623f7
A
2042 for( line = 0; line < height; line++)
2043 {
2044 for( col = 0; col < width; col++)
2045 {
13f56ec4
A
2046 if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16)
2047 + sourceRow * (((sy + (col * c) + (line * d)) >> 16))];
b0d623f7
A
2048 if (backPtr) {
2049 if (kSave & flags) {
2050 back = *(dst + col);
2051 *backPtr++ = back;
2052 } else
2053 back = *backPtr++;
2054 }
2055 if (kDataIndexed & flags) {
2056 out = ( (CLUT_MASK_R & (vc_clut[data*3 + 0])) CLUT_SHIFT_R)
2057 | ( (CLUT_MASK_G & (vc_clut[data*3 + 1])) CLUT_SHIFT_G)
2058 | ( (CLUT_MASK_B & (vc_clut[data*3 + 2])) CLUT_SHIFT_B);
2059 } else if (kDataAlpha & flags) {
2060 out = (((((back & MASK_R) * data) + MASK_R_8) >> 8) & MASK_R)
2061 | (((((back & MASK_G) * data) + MASK_G_8) >> 8) & MASK_G)
2062 | (((((back & MASK_B) * data) + MASK_B_8) >> 8) & MASK_B);
fe8ab488
A
2063 if (vc_progress_white) out += (((0xff - data) & CLUT_MASK_R) CLUT_SHIFT_R)
2064 | (((0xff - data) & CLUT_MASK_G) CLUT_SHIFT_G)
2065 | (((0xff - data) & CLUT_MASK_B) CLUT_SHIFT_B);
2066 } else if (kDataBack & flags)
b0d623f7 2067 out = back;
fe8ab488
A
2068 else
2069 out = data;
b0d623f7
A
2070 *(dst + col) = out;
2071 }
2072 dst = (volatile unsigned short *) (((volatile char*)dst) + vinfo.v_rowbytes);
2073 if (backPtr)
2074 backPtr += backRow - width;
55e303ae
A
2075 }
2076}
2077
13f56ec4 2078
b0d623f7
A
2079static void vc_blit_rect_32(int x, int y, int bx,
2080 int width, int height,
2081 int sourceRow, int backRow,
2082 const unsigned char * dataPtr,
2083 unsigned int * backPtr,
2084 unsigned int flags)
55e303ae
A
2085{
2086 volatile unsigned int * dst;
2087 int line, col;
b0d623f7 2088 unsigned int data = 0, out = 0, back = 0;
13f56ec4
A
2089 int sx, sy, a, b, c, d;
2090 int scale = 0x10000;
2091
2092 a = vc_rotate_matr[kDataRotate & flags][0][0] * scale;
2093 b = vc_rotate_matr[kDataRotate & flags][0][1] * scale;
2094 c = vc_rotate_matr[kDataRotate & flags][1][0] * scale;
2095 d = vc_rotate_matr[kDataRotate & flags][1][1] * scale;
2096 sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0;
2097 sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0;
2098
2099 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr;
2100 else if (1 == sourceRow) a = 0;
2101
b0d623f7
A
2102 if (backPtr)
2103 backPtr += bx;
55e303ae
A
2104 dst = (volatile unsigned int *) (vinfo.v_baseaddr +
2105 (y * vinfo.v_rowbytes) +
2106 (x * 4));
2107
b0d623f7
A
2108 for( line = 0; line < height; line++)
2109 {
2110 for( col = 0; col < width; col++)
2111 {
13f56ec4
A
2112 if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16)
2113 + sourceRow * (((sy + (col * c) + (line * d)) >> 16))];
b0d623f7
A
2114 if (backPtr) {
2115 if (kSave & flags) {
2116 back = *(dst + col);
2117 *backPtr++ = back;
2118 } else
2119 back = *backPtr++;
2120 }
2121 if (kDataIndexed & flags) {
2122 out = (vc_clut[data*3 + 0] << 16)
2123 | (vc_clut[data*3 + 1] << 8)
2124 | (vc_clut[data*3 + 2]);
2125 } else if (kDataAlpha & flags) {
2126 out = (((((back & 0x00ff00ff) * data) + 0x00ff00ff) >> 8) & 0x00ff00ff)
2127 | (((((back & 0x0000ff00) * data) + 0x0000ff00) >> 8) & 0x0000ff00);
fe8ab488
A
2128 if (vc_progress_white) out += ((0xff - data) << 16)
2129 | ((0xff - data) << 8)
2130 | (0xff - data);
2131 } else if (kDataBack & flags)
b0d623f7 2132 out = back;
fe8ab488
A
2133 else
2134 out = data;
b0d623f7
A
2135 *(dst + col) = out;
2136 }
2137 dst = (volatile unsigned int *) (((volatile char*)dst) + vinfo.v_rowbytes);
2138 if (backPtr)
2139 backPtr += backRow - width;
b0d623f7
A
2140 }
2141}
55e303ae 2142
b0d623f7
A
2143static void vc_blit_rect_30(int x, int y, int bx,
2144 int width, int height,
2145 int sourceRow, int backRow,
2146 const unsigned char * dataPtr,
2147 unsigned int * backPtr,
2148 unsigned int flags)
2149{
2150 volatile unsigned int * dst;
2151 int line, col;
2152 unsigned int data = 0, out = 0, back = 0;
2153 unsigned long long exp;
13f56ec4
A
2154 int sx, sy, a, b, c, d;
2155 int scale = 0x10000;
2156
2157 a = vc_rotate_matr[kDataRotate & flags][0][0] * scale;
2158 b = vc_rotate_matr[kDataRotate & flags][0][1] * scale;
2159 c = vc_rotate_matr[kDataRotate & flags][1][0] * scale;
2160 d = vc_rotate_matr[kDataRotate & flags][1][1] * scale;
2161 sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0;
2162 sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0;
2163
2164 if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr;
2165 else if (1 == sourceRow) a = 0;
2166
b0d623f7
A
2167 if (backPtr)
2168 backPtr += bx;
b0d623f7
A
2169 dst = (volatile unsigned int *) (vinfo.v_baseaddr +
2170 (y * vinfo.v_rowbytes) +
2171 (x * 4));
55e303ae 2172
b0d623f7
A
2173 for( line = 0; line < height; line++)
2174 {
2175 for( col = 0; col < width; col++)
2176 {
3e170ce0
A
2177 if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16)
2178 + sourceRow * (((sy + (col * c) + (line * d)) >> 16))];
b0d623f7
A
2179 if (backPtr) {
2180 if (kSave & flags) {
2181 back = *(dst + col);
2182 *backPtr++ = back;
2183 } else
2184 back = *backPtr++;
2185 }
2186 if (kDataIndexed & flags) {
2187 out = (vc_clut[data*3 + 0] << 22)
2188 | (vc_clut[data*3 + 1] << 12)
2189 | (vc_clut[data*3 + 2] << 2);
2190 } else if (kDataAlpha & flags) {
2191 exp = back;
2192 exp = (((((exp & 0x3FF003FF) * data) + 0x0FF000FF) >> 8) & 0x3FF003FF)
2193 | (((((exp & 0x000FFC00) * data) + 0x0003FC00) >> 8) & 0x000FFC00);
2194 out = (unsigned int)exp;
fe8ab488
A
2195 if (vc_progress_white) out += ((0xFF - data) << 22)
2196 | ((0xFF - data) << 12)
2197 | ((0xFF - data) << 2);
2198 } else if (kDataBack & flags)
b0d623f7 2199 out = back;
fe8ab488
A
2200 else
2201 out = data;
b0d623f7
A
2202 *(dst + col) = out;
2203 }
2204 dst = (volatile unsigned int *) (((volatile char*)dst) + vinfo.v_rowbytes);
2205 if (backPtr)
2206 backPtr += backRow - width;
55e303ae
A
2207 }
2208}
7ddcb079 2209
fe8ab488
A
2210static void vc_clean_boot_graphics(void)
2211{
2212 // clean up possible FDE login graphics
2213 vc_progress_set(FALSE, 0);
2214 const unsigned char *
2215 color = (typeof(color))(uintptr_t)(vc_progress_white ? 0x00000000 : 0xBFBFBFBF);
2216 vc_blit_rect(0, 0, 0, vinfo.v_width, vinfo.v_height, 0, 0, color, NULL, 0);
2217}
7ddcb079
A
2218
2219/*
2220 * Routines to render the lzss image format
2221 */
2222
2223struct lzss_image_state {
2224 uint32_t col;
2225 uint32_t row;
2226 uint32_t width;
2227 uint32_t height;
2228 uint32_t bytes_per_row;
2229 volatile uint32_t * row_start;
2230 const uint8_t* clut;
2231};
2232typedef struct lzss_image_state lzss_image_state;
2233
2234// returns 0 if OK, 1 if error
2235static inline int
2236vc_decompress_lzss_next_pixel (int next_data, lzss_image_state* state)
2237{
2238 uint32_t palette_index = 0;
2239 uint32_t pixel_value = 0;
2240
2241 palette_index = next_data * 3;
2242
2243 pixel_value = ( (uint32_t) state->clut[palette_index + 0] << 16)
2244 | ( (uint32_t) state->clut[palette_index + 1] << 8)
2245 | ( (uint32_t) state->clut[palette_index + 2]);
2246
2247 *(state->row_start + state->col) = pixel_value;
2248
2249 if (++state->col >= state->width) {
2250 state->col = 0;
2251 if (++state->row >= state->height) {
2252 return 1;
2253 }
2254 state->row_start = (volatile uint32_t *) (((uintptr_t)state->row_start) + state->bytes_per_row);
2255 }
2256 return 0;
2257}
2258
2259
2260/*
2261 * Blit an lzss compressed image to the framebuffer
2262 * Assumes 32 bit screen (which is everything we ship at the moment)
2263 * The function vc_display_lzss_icon was copied from libkern/mkext.c, then modified.
2264 */
2265
2266/*
2267 * TODO: Does lzss use too much stack? 4096 plus bytes...
2268 * Can probably chop it down by 1/2.
2269 */
2270
2271/**************************************************************
2272 LZSS.C -- A Data Compression Program
2273***************************************************************
2274 4/6/1989 Haruhiko Okumura
2275 Use, distribute, and modify this program freely.
2276 Please send me your improved versions.
2277 PC-VAN SCIENCE
2278 NIFTY-Serve PAF01022
2279 CompuServe 74050,1022
2280
2281**************************************************************/
2282
2283#define N 4096 /* size of ring buffer - must be power of 2 */
2284#define F 18 /* upper limit for match_length */
2285#define THRESHOLD 2 /* encode string into position and length
2286 if match_length is greater than this */
2287
2288// returns 0 if OK, 1 if error
2289// x and y indicate upper left corner of image location on screen
2290int
2291vc_display_lzss_icon(uint32_t dst_x, uint32_t dst_y,
2292 uint32_t image_width, uint32_t image_height,
2293 const uint8_t *compressed_image,
2294 uint32_t compressed_size,
2295 const uint8_t *clut)
2296{
2297 uint32_t* image_start;
2298 uint32_t bytes_per_pixel = 4;
2299 uint32_t bytes_per_row = vinfo.v_rowbytes;
2300
fe8ab488
A
2301 vc_clean_boot_graphics();
2302
7ddcb079
A
2303 image_start = (uint32_t *) (vinfo.v_baseaddr + (dst_y * bytes_per_row) + (dst_x * bytes_per_pixel));
2304
2305 lzss_image_state state = {0, 0, image_width, image_height, bytes_per_row, image_start, clut};
2306
2307 int rval = 0;
2308
2309 const uint8_t *src = compressed_image;
2310 uint32_t srclen = compressed_size;
2311
2312 /* ring buffer of size N, with extra F-1 bytes to aid string comparison */
2313 uint8_t text_buf[N + F - 1];
2314 const uint8_t *srcend = src + srclen;
2315 int i, j, k, r, c;
2316 unsigned int flags;
2317
2318 srcend = src + srclen;
2319 for (i = 0; i < N - F; i++)
2320 text_buf[i] = ' ';
2321 r = N - F;
2322 flags = 0;
2323 for ( ; ; ) {
2324 if (((flags >>= 1) & 0x100) == 0) {
2325 if (src < srcend) c = *src++; else break;
2326 flags = c | 0xFF00; /* uses higher byte cleverly */
2327 } /* to count eight */
2328 if (flags & 1) {
2329 if (src < srcend) c = *src++; else break;
2330 rval = vc_decompress_lzss_next_pixel(c, &state);
2331 if (rval != 0)
2332 return rval;
2333 text_buf[r++] = c;
2334 r &= (N - 1);
2335 } else {
2336 if (src < srcend) i = *src++; else break;
2337 if (src < srcend) j = *src++; else break;
2338 i |= ((j & 0xF0) << 4);
2339 j = (j & 0x0F) + THRESHOLD;
2340 for (k = 0; k <= j; k++) {
2341 c = text_buf[(i + k) & (N - 1)];
2342 rval = vc_decompress_lzss_next_pixel(c, &state);
2343 if (rval != 0 )
2344 return rval;
2345 text_buf[r++] = c;
2346 r &= (N - 1);
2347 }
2348 }
2349 }
2350 return 0;
2351}
2352
2353void noroot_icon_test(void) {
2354 boolean_t o_vc_progress_enable = vc_progress_enable;
2355
2356 vc_progress_enable = 1;
2357
2358 PE_display_icon( 0, "noroot");
2359
2360 vc_progress_enable = o_vc_progress_enable;
2361}
2362
55e303ae
A
2363
2364void vc_display_icon( vc_progress_element * desc,
2365 const unsigned char * data )
2366{
2367 int x, y, width, height;
2368
2369 if( vc_progress_enable && vc_clut) {
2370
fe8ab488
A
2371 vc_clean_boot_graphics();
2372
55e303ae
A
2373 width = desc->width;
2374 height = desc->height;
2375 x = desc->dx;
2376 y = desc->dy;
2377 if( 1 & desc->flags) {
2378 x += ((vinfo.v_width - width) / 2);
2379 y += ((vinfo.v_height - height) / 2);
2380 }
b0d623f7 2381 vc_blit_rect( x, y, 0, width, height, width, 0, data, NULL, kDataIndexed );
55e303ae
A
2382 }
2383}
2384
2385void
2386vc_progress_initialize( vc_progress_element * desc,
13f56ec4
A
2387 const unsigned char * data1x,
2388 const unsigned char * data2x,
fe8ab488 2389 const unsigned char * data3x,
55e303ae
A
2390 const unsigned char * clut )
2391{
fe8ab488 2392 uint64_t abstime;
91447636 2393
13f56ec4 2394 if( (!clut) || (!desc) || (!data1x))
55e303ae
A
2395 return;
2396 vc_clut = clut;
2397 vc_clut8 = clut;
2398
2399 vc_progress = desc;
13f56ec4
A
2400 vc_progress_data[0] = data1x;
2401 vc_progress_data[1] = data2x;
fe8ab488 2402 vc_progress_data[2] = data3x;
55e303ae 2403 if( 2 & vc_progress->flags)
13f56ec4 2404 vc_progress_alpha = data1x
55e303ae
A
2405 + vc_progress->count * vc_progress->width * vc_progress->height;
2406 else
2407 vc_progress_alpha = NULL;
55e303ae 2408
91447636 2409 thread_call_setup(&vc_progress_call, vc_progress_task, NULL);
91447636 2410 clock_interval_to_absolutetime_interval(vc_progress->time, 1000 * 1000, &abstime);
b0d623f7 2411 vc_progress_interval = (uint32_t)abstime;
fe8ab488
A
2412
2413 thread_call_setup(&vc_progressmeter_call, vc_progressmeter_task, NULL);
2414 clock_interval_to_absolutetime_interval(1000 / 8, 1000 * 1000, &abstime);
2415 vc_progressmeter_interval = (uint32_t)abstime;
2416
55e303ae
A
2417}
2418
b0d623f7 2419void
2d21ac55 2420vc_progress_set(boolean_t enable, uint32_t vc_delay)
55e303ae
A
2421{
2422 spl_t s;
2d21ac55 2423 void *saveBuf = NULL;
55e303ae
A
2424 vm_size_t saveLen = 0;
2425 unsigned int count;
2426 unsigned int index;
2427 unsigned char pdata8;
2428 unsigned short pdata16;
2429 unsigned short * buf16;
2430 unsigned int pdata32;
2431 unsigned int * buf32;
2432
fe8ab488
A
2433
2434 if (kBootArgsFlagBlack & ((boot_args *) PE_state.bootArgs)->flags) return;
2435
2436 if (1 & vc_progress_withmeter)
2437 {
2438 if (enable) internal_enable_progressmeter(kProgressMeterKernel);
2439
2440 s = splhigh();
2441 simple_lock(&vc_progress_lock);
2442
2443 if( vc_progress_enable != enable) {
2444 vc_progress_enable = enable;
2445 if( enable)
2446 {
2447 vc_progressmeter_count = 0;
2448 clock_interval_to_deadline(vc_delay,
2449 1000 * 1000 * 1000 /*second scale*/,
2450 &vc_progressmeter_deadline);
2451 thread_call_enter_delayed(&vc_progressmeter_call, vc_progressmeter_deadline);
2452 }
2453 else thread_call_cancel(&vc_progressmeter_call);
2454 }
2455
2456 simple_unlock(&vc_progress_lock);
2457 splx(s);
2458
2459 if (!enable) internal_enable_progressmeter(kProgressMeterOff);
55e303ae 2460 return;
fe8ab488
A
2461 }
2462
2463
2464 if(!vc_progress) return;
55e303ae
A
2465
2466 if( enable) {
fe8ab488 2467 saveLen = (vc_progress->width * vc_uiscale) * (vc_progress->height * vc_uiscale) * vinfo.v_depth / 8;
55e303ae
A
2468 saveBuf = kalloc( saveLen );
2469
2470 switch( vinfo.v_depth) {
2471 case 8 :
2472 for( count = 0; count < 256; count++) {
2473 vc_revclut8[count] = vc_clut[0x01 * 3];
2474 pdata8 = (vc_clut[0x01 * 3] * count + 0x0ff) >> 8;
2475 for( index = 0; index < 256; index++) {
2476 if( (pdata8 == vc_clut[index * 3 + 0]) &&
2477 (pdata8 == vc_clut[index * 3 + 1]) &&
2478 (pdata8 == vc_clut[index * 3 + 2])) {
2479 vc_revclut8[count] = index;
2480 break;
2481 }
2482 }
2483 }
91447636 2484 memset( saveBuf, 0x01, saveLen );
55e303ae
A
2485 break;
2486
2487 case 16 :
2488 buf16 = (unsigned short *) saveBuf;
2d21ac55
A
2489 pdata16 = ((vc_clut[0x01 * 3 + 0] & CLUT_MASK_R) CLUT_SHIFT_R)
2490 | ((vc_clut[0x01 * 3 + 0] & CLUT_MASK_G) CLUT_SHIFT_G)
2491 | ((vc_clut[0x01 * 3 + 0] & CLUT_MASK_B) CLUT_SHIFT_B);
55e303ae
A
2492 for( count = 0; count < saveLen / 2; count++)
2493 buf16[count] = pdata16;
2494 break;
2495
2496 case 32 :
2497 buf32 = (unsigned int *) saveBuf;
2498 pdata32 = ((vc_clut[0x01 * 3 + 0] & 0xff) << 16)
2499 | ((vc_clut[0x01 * 3 + 1] & 0xff) << 8)
2500 | ((vc_clut[0x01 * 3 + 2] & 0xff) << 0);
2501 for( count = 0; count < saveLen / 4; count++)
2502 buf32[count] = pdata32;
2503 break;
2504 }
2505 }
2506
2507 s = splhigh();
2508 simple_lock(&vc_progress_lock);
2509
2510 if( vc_progress_enable != enable) {
2511 vc_progress_enable = enable;
2512 if( enable) {
2513 vc_needsave = TRUE;
2514 vc_saveunder = saveBuf;
2515 vc_saveunder_len = saveLen;
060df5ea
A
2516 saveBuf = NULL;
2517 saveLen = 0;
2518 vc_progress_count = 0;
13f56ec4 2519 vc_progress_angle = 0;
91447636 2520
2d21ac55
A
2521 clock_interval_to_deadline(vc_delay,
2522 1000 * 1000 * 1000 /*second scale*/,
2523 &vc_progress_deadline);
91447636
A
2524 thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline);
2525
55e303ae
A
2526 } else {
2527 if( vc_saveunder) {
2528 saveBuf = vc_saveunder;
2529 saveLen = vc_saveunder_len;
2d21ac55 2530 vc_saveunder = NULL;
55e303ae
A
2531 vc_saveunder_len = 0;
2532 }
91447636
A
2533
2534 thread_call_cancel(&vc_progress_call);
55e303ae
A
2535 }
2536 }
2537
2538 simple_unlock(&vc_progress_lock);
2539 splx(s);
2540
2541 if( saveBuf)
2542 kfree( saveBuf, saveLen );
2543}
2544
b0d623f7 2545
3e170ce0
A
2546static uint32_t vc_progressmeter_range(uint32_t pos)
2547{
2548 uint32_t ret;
2549
2550 if (pos > kProgressMeterEnd) pos = kProgressMeterEnd;
2551 ret = vc_progress_meter_start
2552 + ((pos * (vc_progress_meter_end - vc_progress_meter_start)) / kProgressMeterEnd);
2553
2554 return (ret);
2555}
2556
fe8ab488
A
2557static void
2558vc_progressmeter_task(__unused void *arg0, __unused void *arg)
2559{
2560 spl_t s;
2561 uint64_t interval;
2562
2563 s = splhigh();
2564 simple_lock(&vc_progress_lock);
2565 if (vc_progressmeter_enable)
2566 {
2567 uint32_t pos = (vc_progressmeter_count >> 13);
3e170ce0 2568 internal_set_progressmeter(vc_progressmeter_range(pos));
fe8ab488
A
2569 if (pos < kProgressMeterEnd)
2570 {
2571 static uint16_t incr[8] = { 10000, 10000, 8192, 4096, 2048, 384, 384, 64 };
2572 vc_progressmeter_count += incr[(pos * 8) / kProgressMeterEnd];
2573
2574 interval = vc_progressmeter_interval;
2575 interval = ((interval * 256) / vc_progressmeter_diskspeed);
2576
2577 clock_deadline_for_periodic_event(interval, mach_absolute_time(), &vc_progressmeter_deadline);
2578 thread_call_enter_delayed(&vc_progressmeter_call, vc_progressmeter_deadline);
2579 }
2580 }
2581 simple_unlock(&vc_progress_lock);
2582 splx(s);
2583}
2584
2585void vc_progress_setdiskspeed(uint32_t speed)
2586{
2587 vc_progressmeter_diskspeed = speed;
2588}
2589
2590
2d21ac55 2591static void
060df5ea 2592vc_progress_task(__unused void *arg0, __unused void *arg)
55e303ae 2593{
fe8ab488
A
2594 spl_t s;
2595 int x, y, width, height;
55e303ae
A
2596 const unsigned char * data;
2597
2598 s = splhigh();
2599 simple_lock(&vc_progress_lock);
2600
2601 if( vc_progress_enable) {
fe8ab488
A
2602
2603 vc_progress_count++;
2604 if( vc_progress_count >= vc_progress->count) {
2605 vc_progress_count = 0;
13f56ec4 2606 vc_progress_angle++;
55e303ae 2607 }
55e303ae 2608
fe8ab488
A
2609 width = (vc_progress->width * vc_uiscale);
2610 height = (vc_progress->height * vc_uiscale);
2611 x = (vc_progress->dx * vc_uiscale);
2612 y = (vc_progress->dy * vc_uiscale);
2613 data = vc_progress_data[vc_uiscale - 1];
2614 if (data)
2615 {
2616 data += vc_progress_count * width * height;
2617 if( 1 & vc_progress->flags) {
2618 x += ((vinfo.v_width - width) / 2);
2619 y += ((vinfo.v_height - height) / 2);
2620 }
2621
2622 assert(((x + width) < (int)vinfo.v_width) &&
2623 ((y + height) < (int)vinfo.v_height));
2624
2625 vc_blit_rect( x, y, 0,
2626 width, height, width, width,
2627 data, vc_saveunder,
2628 kDataAlpha
2629 | (vc_progress_angle & kDataRotate)
2630 | (vc_needsave ? kSave : 0) );
2631 vc_needsave = FALSE;
2632
2633 clock_deadline_for_periodic_event(vc_progress_interval, mach_absolute_time(), &vc_progress_deadline);
2634 thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline);
2635 }
55e303ae
A
2636 }
2637 simple_unlock(&vc_progress_lock);
2638 splx(s);
2639}
2640
2641/*
2642 * Generic Console (Front-End): Master Control
2643 * -------------------------------------------
2644 */
2645
b0d623f7 2646#if defined (__i386__) || defined (__x86_64__)
0c530ab8 2647#include <pexpert/i386/boot.h>
b0d623f7 2648#endif
55e303ae
A
2649
2650static boolean_t gc_acquired = FALSE;
2651static boolean_t gc_graphics_boot = FALSE;
2d21ac55 2652static boolean_t gc_desire_text = FALSE;
fe8ab488 2653static boolean_t gc_paused_progress;
55e303ae 2654
060df5ea 2655static uint64_t lastVideoPhys = 0;
b0d623f7
A
2656static vm_offset_t lastVideoVirt = 0;
2657static vm_size_t lastVideoSize = 0;
0c530ab8 2658static boolean_t lastVideoMapped = FALSE;
060df5ea
A
2659static void
2660gc_pause( boolean_t pause, boolean_t graphics_now )
2661{
2662 spl_t s;
2663
2664 s = splhigh( );
2665 VCPUTC_LOCK_LOCK( );
2666
2667 disableConsoleOutput = (pause && !console_is_serial());
2668 gc_enabled = (!pause && !graphics_now);
2669
2670 VCPUTC_LOCK_UNLOCK( );
2671
2672 simple_lock(&vc_progress_lock);
2673
fe8ab488
A
2674 if (pause)
2675 {
2676 gc_paused_progress = vc_progress_enable;
2677 vc_progress_enable = FALSE;
2678 }
2679 else vc_progress_enable = gc_paused_progress;
2680
2681 if (vc_progress_enable)
2682 {
2683 if (1 & vc_progress_withmeter) thread_call_enter_delayed(&vc_progressmeter_call, vc_progressmeter_deadline);
2684 else
2685 thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline);
2686 }
060df5ea
A
2687
2688 simple_unlock(&vc_progress_lock);
2689 splx(s);
2690}
2691
13f56ec4
A
2692static void
2693vc_initialize(__unused struct vc_info * vinfo_p)
2694{
2695
2696 vinfo.v_rows = vinfo.v_height / ISO_CHAR_HEIGHT;
2697 vinfo.v_columns = vinfo.v_width / ISO_CHAR_WIDTH;
2698 vinfo.v_rowscanbytes = ((vinfo.v_depth + 7) / 8) * vinfo.v_width;
fe8ab488
A
2699 vc_uiscale = vinfo.v_scale;
2700 if (vc_uiscale > kMaxProgressData) vc_uiscale = kMaxProgressData;
2701 else if (!vc_uiscale) vc_uiscale = 1;
13f56ec4
A
2702}
2703
55e303ae 2704void
2d21ac55 2705initialize_screen(PE_Video * boot_vinfo, unsigned int op)
55e303ae 2706{
2d21ac55 2707 unsigned int fbsize = 0;
b0d623f7 2708 vm_offset_t newVideoVirt = 0;
2d21ac55 2709 boolean_t graphics_now;
55e303ae
A
2710 ppnum_t fbppage;
2711
2712 if ( boot_vinfo )
2713 {
2d21ac55 2714 struct vc_info new_vinfo = vinfo;
55e303ae
A
2715 /*
2716 * First, check if we are changing the size and/or location of the framebuffer
2717 */
2d21ac55 2718 new_vinfo.v_name[0] = 0;
060df5ea
A
2719 new_vinfo.v_physaddr = boot_vinfo->v_baseAddr & ~3; /* Get the physical address */
2720#ifndef __LP64__
2721 new_vinfo.v_physaddr |= (((uint64_t) boot_vinfo->v_baseAddrHigh) << 32);
2722#endif
2723 if (kPEBaseAddressChange != op)
2724 {
13f56ec4
A
2725 new_vinfo.v_width = (unsigned int)boot_vinfo->v_width;
2726 new_vinfo.v_height = (unsigned int)boot_vinfo->v_height;
2727 new_vinfo.v_depth = (unsigned int)boot_vinfo->v_depth;
2728 new_vinfo.v_rowbytes = (unsigned int)boot_vinfo->v_rowBytes;
b0d623f7 2729#if defined(__i386__) || defined(__x86_64__)
13f56ec4 2730 new_vinfo.v_type = (unsigned int)boot_vinfo->v_display;
0c530ab8 2731#else
13f56ec4 2732 new_vinfo.v_type = 0;
0c530ab8 2733#endif
316670eb
A
2734 unsigned int scale = (unsigned int)boot_vinfo->v_scale;
2735 if (scale == kPEScaleFactor1x )
2736 new_vinfo.v_scale = kPEScaleFactor1x;
2737 else if (scale == kPEScaleFactor2x)
2738 new_vinfo.v_scale = kPEScaleFactor2x;
2739 else /* Scale factor not set, default to 1x */
2740 new_vinfo.v_scale = kPEScaleFactor1x;
2741
060df5ea 2742 }
2d21ac55
A
2743
2744 if (!lastVideoMapped)
060df5ea 2745 kprintf("initialize_screen: b=%08llX, w=%08X, h=%08X, r=%08X, d=%08X\n", /* (BRINGUP) */
2d21ac55 2746 new_vinfo.v_physaddr, new_vinfo.v_width, new_vinfo.v_height, new_vinfo.v_rowbytes, new_vinfo.v_type); /* (BRINGUP) */
0c530ab8 2747
2d21ac55 2748 if (!new_vinfo.v_physaddr) /* Check to see if we have a framebuffer */
55e303ae
A
2749 {
2750 kprintf("initialize_screen: No video - forcing serial mode\n"); /* (BRINGUP) */
2d21ac55 2751 new_vinfo.v_depth = 0; /* vc routines are nop */
55e303ae
A
2752 (void)switch_to_serial_console(); /* Switch into serial mode */
2753 gc_graphics_boot = FALSE; /* Say we are not in graphics mode */
2754 disableConsoleOutput = FALSE; /* Allow printfs to happen */
2755 gc_acquired = TRUE;
2756 }
2757 else
2758 {
2759 /*
060df5ea
A
2760 * If VM is up, we are given a virtual address, unless b0 is set to indicate physical.
2761 */
2762 if ((kernel_map != VM_MAP_NULL) && (0 == (1 & boot_vinfo->v_baseAddr)))
55e303ae
A
2763 {
2764 fbppage = pmap_find_phys(kernel_pmap, (addr64_t)boot_vinfo->v_baseAddr); /* Get the physical address of frame buffer */
2765 if(!fbppage) /* Did we find it? */
2766 {
2d21ac55 2767 panic("initialize_screen: Strange framebuffer - addr = %08X\n", (uint32_t)boot_vinfo->v_baseAddr);
55e303ae 2768 }
fe8ab488 2769 new_vinfo.v_physaddr = (((uint64_t)fbppage) << PAGE_SHIFT) | (boot_vinfo->v_baseAddr & PAGE_MASK); /* Get the physical address */
55e303ae
A
2770 }
2771
2d21ac55 2772 if (boot_vinfo->v_length != 0)
b0d623f7 2773 fbsize = (unsigned int) round_page(boot_vinfo->v_length);
2d21ac55 2774 else
b0d623f7 2775 fbsize = (unsigned int) round_page(new_vinfo.v_height * new_vinfo.v_rowbytes); /* Remember size */
2d21ac55 2776
55e303ae 2777
2d21ac55 2778 if ((lastVideoPhys != new_vinfo.v_physaddr) || (fbsize > lastVideoSize)) /* Did framebuffer change location or get bigger? */
55e303ae 2779 {
b0d623f7 2780 unsigned int flags = VM_WIMG_IO;
060df5ea 2781 newVideoVirt = io_map_spec((vm_map_offset_t)new_vinfo.v_physaddr, fbsize, flags); /* Allocate address space for framebuffer */
2d21ac55
A
2782 }
2783 }
2784
2785 if (newVideoVirt != 0)
2786 new_vinfo.v_baseaddr = newVideoVirt + boot_vinfo->v_offset; /* Set the new framebuffer address */
2787 else
2788 new_vinfo.v_baseaddr = lastVideoVirt + boot_vinfo->v_offset; /* Set the new framebuffer address */
593a1d5f 2789
b0d623f7
A
2790#if defined(__x86_64__)
2791 // Adjust the video buffer pointer to point to where it is in high virtual (above the hole)
6d2010ae 2792 new_vinfo.v_baseaddr |= (VM_MIN_KERNEL_ADDRESS & ~LOW_4GB_MASK);
b0d623f7
A
2793#endif
2794
2d21ac55
A
2795 /* Update the vinfo structure atomically with respect to the vc_progress task if running */
2796 if (vc_progress)
2797 {
2798 simple_lock(&vc_progress_lock);
2799 vinfo = new_vinfo;
2800 simple_unlock(&vc_progress_lock);
2801 }
2802 else
2803 {
2804 vinfo = new_vinfo;
2805 }
2806
2807 // If we changed the virtual address, remove the old mapping
2808 if (newVideoVirt != 0)
2809 {
2810 if (lastVideoVirt) /* Was the framebuffer mapped before? */
2811 {
fe8ab488
A
2812 /* XXX why did this ever succeed? */
2813 /* TODO: Consider this. */
2814 if (!TEST_PAGE_SIZE_4K && lastVideoMapped) /* Was this not a special pre-VM mapping? */
2d21ac55
A
2815 {
2816 pmap_remove(kernel_pmap, trunc_page_64(lastVideoVirt),
2817 round_page_64(lastVideoVirt + lastVideoSize)); /* Toss mappings */
2818 }
2819 if(lastVideoMapped) /* Was this not a special pre-VM mapping? */
2820 {
2821 kmem_free(kernel_map, lastVideoVirt, lastVideoSize); /* Toss kernel addresses */
2822 }
2823 }
060df5ea 2824 lastVideoPhys = new_vinfo.v_physaddr; /* Remember the framebuffer address */
2d21ac55
A
2825 lastVideoSize = fbsize; /* Remember the size */
2826 lastVideoVirt = newVideoVirt; /* Remember the virtual framebuffer address */
2827 lastVideoMapped = (NULL != kernel_map);
55e303ae
A
2828 }
2829
060df5ea
A
2830 if (kPEBaseAddressChange != op)
2831 {
55e303ae
A
2832 // Graphics mode setup by the booter.
2833
2834 gc_ops.initialize = vc_initialize;
2835 gc_ops.enable = vc_enable;
2836 gc_ops.paint_char = vc_paint_char;
2837 gc_ops.scroll_down = vc_scroll_down;
2838 gc_ops.scroll_up = vc_scroll_up;
2839 gc_ops.clear_screen = vc_clear_screen;
2840 gc_ops.hide_cursor = vc_reverse_cursor;
2841 gc_ops.show_cursor = vc_reverse_cursor;
2842 gc_ops.update_color = vc_update_color;
060df5ea 2843 gc_initialize(&vinfo);
55e303ae 2844 }
55e303ae
A
2845 }
2846
060df5ea 2847 graphics_now = gc_graphics_boot && !gc_desire_text;
55e303ae
A
2848 switch ( op )
2849 {
2850 case kPEGraphicsMode:
55e303ae 2851 gc_graphics_boot = TRUE;
2d21ac55 2852 gc_desire_text = FALSE;
55e303ae
A
2853 break;
2854
2855 case kPETextMode:
b0d623f7 2856 disable_debug_output = FALSE;
55e303ae
A
2857 gc_graphics_boot = FALSE;
2858 break;
2859
2860 case kPEAcquireScreen:
2861 if ( gc_acquired ) break;
3e170ce0 2862 vc_progress_set( graphics_now, (kVCDarkReboot & vc_user_options) ? 120 : vc_acquire_delay );
2d21ac55 2863 gc_enable( !graphics_now );
55e303ae 2864 gc_acquired = TRUE;
2d21ac55 2865 gc_desire_text = FALSE;
55e303ae
A
2866 break;
2867
060df5ea
A
2868 case kPEDisableScreen:
2869 if (gc_acquired)
2870 {
2871 gc_pause( TRUE, graphics_now );
2872 }
2873 break;
2874
55e303ae 2875 case kPEEnableScreen:
060df5ea
A
2876 if (gc_acquired)
2877 {
2878 gc_pause( FALSE, graphics_now );
2879 }
55e303ae
A
2880 break;
2881
2882 case kPETextScreen:
2d21ac55
A
2883 if ( console_is_serial() ) break;
2884
b0d623f7 2885 disable_debug_output = FALSE;
2d21ac55
A
2886 if ( gc_acquired == FALSE )
2887 {
2888 gc_desire_text = TRUE;
2889 break;
2890 }
55e303ae
A
2891 if ( gc_graphics_boot == FALSE ) break;
2892
2893 vc_progress_set( FALSE, 0 );
b0d623f7 2894 vc_enable_progressmeter( FALSE );
55e303ae
A
2895 gc_enable( TRUE );
2896 break;
2897
55e303ae
A
2898 case kPEReleaseScreen:
2899 gc_acquired = FALSE;
2d21ac55 2900 gc_desire_text = FALSE;
55e303ae 2901 gc_enable( FALSE );
316670eb
A
2902 if ( gc_graphics_boot == FALSE ) break;
2903
55e303ae 2904 vc_progress_set( FALSE, 0 );
fe8ab488
A
2905 vc_acquire_delay = kProgressReacquireDelay;
2906 vc_enable_progressmeter(FALSE);
2907 vc_progress_white = TRUE;
2908 vc_progress_withmeter &= ~1;
55e303ae 2909 vc_clut8 = NULL;
55e303ae 2910 break;
fe8ab488
A
2911
2912
2913 case kPERefreshBootGraphics:
2914 {
2915 spl_t s;
2916 boolean_t save;
2917
2918 if (kBootArgsFlagBlack & ((boot_args *) PE_state.bootArgs)->flags) break;
2919
2920 save = vc_progress_white;
2921 vc_progress_white = (0 != (kBootArgsFlagBlackBg & ((boot_args *) PE_state.bootArgs)->flags));
2922
2923 internal_enable_progressmeter(kProgressMeterKernel);
2924
2925 s = splhigh();
2926 simple_lock(&vc_progress_lock);
2927
2928 vc_progressmeter_drawn = 0;
3e170ce0 2929 internal_set_progressmeter(vc_progressmeter_range(vc_progressmeter_count >> 13));
fe8ab488
A
2930
2931 simple_unlock(&vc_progress_lock);
2932 splx(s);
2933
2934 internal_enable_progressmeter(kProgressMeterOff);
2935 vc_progress_white = save;
2936 }
55e303ae 2937 }
55e303ae 2938}
55e303ae 2939
b7266188
A
2940void
2941dim_screen(void)
2942{
2943 unsigned int *p, *endp, *row;
2944 int col, rowline, rowlongs;
2945 register unsigned int mask;
2946
2947 if(!vinfo.v_depth)
2948 return;
2949
2950 if ( vinfo.v_depth == 32 )
2951 mask = 0x007F7F7F;
2952 else if ( vinfo.v_depth == 30 )
2953 mask = (0x1ff<<20) | (0x1ff<<10) | 0x1ff;
2954 else if ( vinfo.v_depth == 16 )
2955 mask = 0x3DEF3DEF;
2956 else
2957 return;
2958
2959 rowline = (int)(vinfo.v_rowscanbytes / 4);
2960 rowlongs = (int)(vinfo.v_rowbytes / 4);
2961
2962 p = (unsigned int*) vinfo.v_baseaddr;
2963 endp = p + (rowlongs * vinfo.v_height);
2964
2965 for (row = p ; row < endp ; row += rowlongs) {
2966 for (p = &row[0], col = 0; col < rowline; col++) {
2967 *p = (*p >> 1) & mask;
2968 ++p;
2969 }
2970 }
2971}
2972
2d21ac55 2973void vcattach(void); /* XXX gcc 4 warning cleanup */
55e303ae
A
2974
2975void
2976vcattach(void)
2977{
55e303ae
A
2978 vm_initialized = TRUE;
2979
3e170ce0
A
2980 const boot_args * bootargs = (typeof(bootargs)) PE_state.bootArgs;
2981
fe8ab488 2982 vc_progress_white = (0 != ((kBootArgsFlagBlackBg | kBootArgsFlagLoginUI)
3e170ce0 2983 & bootargs->flags));
fe8ab488 2984 PE_parse_boot_argn("meter", &vc_progress_withmeter, sizeof(vc_progress_withmeter));
3e170ce0
A
2985
2986 if (kBootArgsFlagInstallUI & bootargs->flags)
2987 {
2988 vc_progress_meter_start = (bootargs->bootProgressMeterStart * kProgressMeterMax) / 65535;
2989 vc_progress_meter_end = (bootargs->bootProgressMeterEnd * kProgressMeterMax) / 65535;
2990 }
2991 else
2992 {
2993 vc_progress_meter_start = 0;
2994 vc_progress_meter_end = kProgressMeterMax;
2995 }
fe8ab488
A
2996 simple_lock_init(&vc_progress_lock, 0);
2997
55e303ae
A
2998 if ( gc_graphics_boot == FALSE )
2999 {
2d21ac55 3000 long index;
55e303ae
A
3001
3002 if ( gc_acquired )
3003 {
2d21ac55 3004 initialize_screen(NULL, kPEReleaseScreen);
55e303ae
A
3005 }
3006
2d21ac55 3007 initialize_screen(NULL, kPEAcquireScreen);
55e303ae
A
3008
3009 for ( index = 0 ; index < msgbufp->msg_bufx ; index++ )
3010 {
6d2010ae
A
3011 if (msgbufp->msg_bufc[index] == '\0') {
3012 continue;
3013 }
3014
55e303ae
A
3015 vcputc( 0, 0, msgbufp->msg_bufc[index] );
3016
3017 if ( msgbufp->msg_bufc[index] == '\n' )
3018 {
3019 vcputc( 0, 0,'\r' );
3020 }
3021 }
3022 }
3023}
b0d623f7 3024
b0d623f7 3025
fe8ab488 3026// redraw progress meter between pixels x1, x2, position at x3
b0d623f7 3027static void
fe8ab488 3028vc_draw_progress_meter(unsigned int flags, int x1, int x2, int x3)
b0d623f7
A
3029{
3030 const unsigned char * data;
3031 int x, w;
3032 int ox, oy;
fe8ab488
A
3033 int endCapPos;
3034 int onoff;
3035 // 1 rounded fill, 0 square end
3036 int style = (0 == (2 & vc_progress_withmeter));
b0d623f7 3037
fe8ab488
A
3038 ox = ((vinfo.v_width - (kProgressBarWidth * vc_uiscale)) / 2);
3039 oy = vinfo.v_height - (vinfo.v_height / 3) - ((kProgressBarHeight * vc_uiscale) / 2);
b0d623f7
A
3040
3041 if (kDataBack == flags)
3042 {
3043 // restore back bits
3044 vc_blit_rect(ox + x1, oy, x1,
fe8ab488
A
3045 x2, (kProgressBarHeight * vc_uiscale), 0, (kProgressBarWidth * vc_uiscale),
3046 NULL, vc_progressmeter_backbuffer, flags);
b0d623f7
A
3047 return;
3048 }
3049
3050 for (x = x1; x < x2; x += w)
3051 {
fe8ab488
A
3052 onoff = (x < x3);
3053 endCapPos = ((style && onoff) ? x3 : (kProgressBarWidth * vc_uiscale));
3054 if (x < (kProgressBarCapWidth * vc_uiscale))
b0d623f7 3055 {
fe8ab488 3056 if (x2 < (kProgressBarCapWidth * vc_uiscale))
b0d623f7
A
3057 w = x2 - x;
3058 else
fe8ab488
A
3059 w = (kProgressBarCapWidth * vc_uiscale) - x;
3060 data = progressmeter_leftcap[vc_uiscale >= 2][onoff];
b0d623f7 3061 data += x;
13f56ec4 3062 vc_blit_rect(ox + x, oy, x, w,
fe8ab488
A
3063 (kProgressBarHeight * vc_uiscale),
3064 (kProgressBarCapWidth * vc_uiscale),
3065 (kProgressBarWidth * vc_uiscale),
3066 data, vc_progressmeter_backbuffer, flags);
b0d623f7 3067 }
fe8ab488 3068 else if (x < (endCapPos - (kProgressBarCapWidth * vc_uiscale)))
b0d623f7 3069 {
fe8ab488 3070 if (x2 < (endCapPos - (kProgressBarCapWidth * vc_uiscale)))
b0d623f7
A
3071 w = x2 - x;
3072 else
fe8ab488
A
3073 w = (endCapPos - (kProgressBarCapWidth * vc_uiscale)) - x;
3074 data = progressmeter_middle[vc_uiscale >= 2][onoff];
13f56ec4 3075 vc_blit_rect(ox + x, oy, x, w,
fe8ab488 3076 (kProgressBarHeight * vc_uiscale),
13f56ec4 3077 1,
fe8ab488
A
3078 (kProgressBarWidth * vc_uiscale),
3079 data, vc_progressmeter_backbuffer, flags);
b0d623f7
A
3080 }
3081 else
3082 {
fe8ab488
A
3083 w = endCapPos - x;
3084 data = progressmeter_rightcap[vc_uiscale >= 2][onoff];
3085 data += x - (endCapPos - (kProgressBarCapWidth * vc_uiscale));
13f56ec4 3086 vc_blit_rect(ox + x, oy, x, w,
fe8ab488
A
3087 (kProgressBarHeight * vc_uiscale),
3088 (kProgressBarCapWidth * vc_uiscale),
3089 (kProgressBarWidth * vc_uiscale),
3090 data, vc_progressmeter_backbuffer, flags);
b0d623f7
A
3091 }
3092 }
3093}
3094
fe8ab488
A
3095extern void IORecordProgressBackbuffer(void * buffer, size_t size, uint32_t theme);
3096
3097static void
3098internal_enable_progressmeter(int new_value)
b0d623f7 3099{
fe8ab488
A
3100 spl_t s;
3101 void * new_buffer;
3102 boolean_t stashBackbuffer;
b0d623f7 3103
fe8ab488
A
3104 stashBackbuffer = FALSE;
3105 new_buffer = NULL;
b0d623f7 3106 if (new_value)
fe8ab488
A
3107 {
3108 new_buffer = kalloc((kProgressBarWidth * vc_uiscale)
3109 * (kProgressBarHeight * vc_uiscale) * sizeof(int));
3110 }
b0d623f7
A
3111
3112 s = splhigh();
3113 simple_lock(&vc_progress_lock);
3114
fe8ab488
A
3115 if (kProgressMeterUser == new_value)
3116 {
3117 if (gc_enabled || !gc_acquired || !gc_graphics_boot
3118 || (kProgressMeterKernel == vc_progressmeter_enable)) new_value = vc_progressmeter_enable;
3119 }
b0d623f7 3120
fe8ab488 3121 if (new_value != vc_progressmeter_enable)
b0d623f7
A
3122 {
3123 if (new_value)
3124 {
fe8ab488
A
3125 if (kProgressMeterOff == vc_progressmeter_enable)
3126 {
3127 vc_progressmeter_backbuffer = new_buffer;
3128 vc_draw_progress_meter(kDataAlpha | kSave, 0, (kProgressBarWidth * vc_uiscale), 0);
3129 new_buffer = NULL;
3130 vc_progressmeter_drawn = 0;
3131 }
3132 vc_progressmeter_enable = new_value;
b0d623f7 3133 }
fe8ab488 3134 else if (vc_progressmeter_backbuffer)
b0d623f7 3135 {
fe8ab488
A
3136 if (kProgressMeterUser == vc_progressmeter_enable)
3137 {
3138 vc_draw_progress_meter(kDataBack, 0, (kProgressBarWidth * vc_uiscale), vc_progressmeter_drawn);
3139 }
3140 else stashBackbuffer = TRUE;
3141 new_buffer = vc_progressmeter_backbuffer;
3142 vc_progressmeter_backbuffer = NULL;
3143 vc_progressmeter_enable = FALSE;
b0d623f7
A
3144 }
3145 }
3146
3147 simple_unlock(&vc_progress_lock);
3148 splx(s);
3149
3150 if (new_buffer)
fe8ab488
A
3151 {
3152 if (stashBackbuffer) IORecordProgressBackbuffer(new_buffer,
3153 (kProgressBarWidth * vc_uiscale)
3154 * (kProgressBarHeight * vc_uiscale)
3155 * sizeof(int),
3156 vc_progress_white);
3157 kfree(new_buffer, (kProgressBarWidth * vc_uiscale)
3158 * (kProgressBarHeight * vc_uiscale) * sizeof(int));
3159 }
3160}
3161
3162static void
3163internal_set_progressmeter(int new_value)
3164{
3165 int x1, x3;
3166 int capRedraw;
3167 // 1 rounded fill, 0 square end
3168 int style = (0 == (2 & vc_progress_withmeter));
3169
3170 if ((new_value < 0) || (new_value > kProgressMeterMax)) return;
3171
3172 if (vc_progressmeter_enable)
3173 {
3174 vc_progressmeter_value = new_value;
3175
3176 capRedraw = (style ? (kProgressBarCapWidth * vc_uiscale) : 0);
3177 x3 = (((kProgressBarWidth * vc_uiscale) - 2 * capRedraw) * vc_progressmeter_value) / kProgressMeterMax;
3178 x3 += (2 * capRedraw);
3179
3180 if (x3 > vc_progressmeter_drawn)
3181 {
3182 x1 = capRedraw;
3183 if (x1 > vc_progressmeter_drawn) x1 = vc_progressmeter_drawn;
3184 vc_draw_progress_meter(kDataAlpha, vc_progressmeter_drawn - x1, x3, x3);
3185 }
3186 else
3187 {
3188 vc_draw_progress_meter(kDataAlpha, x3 - capRedraw, vc_progressmeter_drawn, x3);
3189 }
3190 vc_progressmeter_drawn = x3;
3191 }
3192}
3193
3194void
3195vc_enable_progressmeter(int new_value)
3196{
3197 if (kProgressMeterKernel == vc_progressmeter_enable)
3198 {
3199 vc_progressmeter_hold = new_value;
3200 }
3201 else
3202 {
3203 internal_enable_progressmeter(new_value ? kProgressMeterUser : kProgressMeterOff);
3204 }
b0d623f7
A
3205}
3206
3207void
3208vc_set_progressmeter(int new_value)
3209{
3210 spl_t s;
b0d623f7
A
3211
3212 s = splhigh();
3213 simple_lock(&vc_progress_lock);
3214
fe8ab488 3215 if (vc_progressmeter_enable && (kProgressMeterKernel != vc_progressmeter_enable))
b0d623f7 3216 {
fe8ab488 3217 internal_set_progressmeter((new_value * kProgressMeterMax) / 100);
b0d623f7 3218 }
fe8ab488 3219
b0d623f7
A
3220 simple_unlock(&vc_progress_lock);
3221 splx(s);
3222}
3223
b0d623f7 3224
3e170ce0
A
3225void
3226vc_set_options(int new_value)
3227{
3228 vc_user_options = new_value;
3229}
3230
3231