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