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