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