X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6601e61aa18bf4f09af135ff61fc7f4771d23b06..db6096698656d32db7df630594bd9617ee54f828:/osfmk/console/video_console.c diff --git a/osfmk/console/video_console.c b/osfmk/console/video_console.c index 9e00806ff..32446eb35 100644 --- a/osfmk/console/video_console.c +++ b/osfmk/console/video_console.c @@ -1,23 +1,29 @@ /* - * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2009 Apple Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * @OSF_FREE_COPYRIGHT@ @@ -85,6 +91,7 @@ #include #include +#include #include #include @@ -95,10 +102,18 @@ #include #include +#include +#include #include +#include #include "iso_font.c" +#if !CONFIG_EMBEDDED +#include "progress_meter_data.c" +#endif + +#include "sys/msgbuf.h" /* * Generic Console (Front-End) @@ -106,11 +121,10 @@ */ struct vc_info vinfo; -/* if panicDialogDesired is true then we use the panic dialog when its */ -/* allowed otherwise we won't use the panic dialog even if it is allowed */ -boolean_t panicDialogDesired; - +void noroot_icon_test(void); + + extern int disableConsoleOutput; static boolean_t gc_enabled = FALSE; static boolean_t gc_initialized = FALSE; @@ -119,22 +133,70 @@ static boolean_t vm_initialized = FALSE; static struct { void (*initialize)(struct vc_info * info); void (*enable)(boolean_t enable); - void (*paint_char)(int xx, int yy, unsigned char ch, int attrs, unsigned char ch_previous, int attrs_previous); - void (*clear_screen)(int xx, int yy, int top, int bottom, int which); - void (*scroll_down)(int num, int top, int bottom); - void (*scroll_up)(int num, int top, int bottom); - void (*hide_cursor)(int xx, int yy); - void (*show_cursor)(int xx, int yy); + void (*paint_char)(unsigned int xx, unsigned int yy, unsigned char ch, + int attrs, unsigned char ch_previous, + int attrs_previous); + void (*clear_screen)(unsigned int xx, unsigned int yy, unsigned int top, + unsigned int bottom, int which); + void (*scroll_down)(int num, unsigned int top, unsigned int bottom); + void (*scroll_up)(int num, unsigned int top, unsigned int bottom); + void (*hide_cursor)(unsigned int xx, unsigned int yy); + void (*show_cursor)(unsigned int xx, unsigned int yy); void (*update_color)(int color, boolean_t fore); } gc_ops; -static unsigned char * gc_buffer_attributes = NULL; -static unsigned char * gc_buffer_characters = NULL; -static unsigned char * gc_buffer_colorcodes = NULL; -static unsigned long gc_buffer_columns = 0; -static unsigned long gc_buffer_rows = 0; -static unsigned long gc_buffer_size = 0; -decl_simple_lock_data(,gc_buffer_lock) +static unsigned char *gc_buffer_attributes; +static unsigned char *gc_buffer_characters; +static unsigned char *gc_buffer_colorcodes; +static unsigned char *gc_buffer_tab_stops; +static uint32_t gc_buffer_columns; +static uint32_t gc_buffer_rows; +static uint32_t gc_buffer_size; + +#if defined(__i386__) || defined(__x86_64__) +decl_simple_lock_data(static, vcputc_lock); + +#define VCPUTC_LOCK_INIT() \ +MACRO_BEGIN \ + simple_lock_init(&vcputc_lock, 0); \ +MACRO_END + +#define VCPUTC_LOCK_LOCK() \ +MACRO_BEGIN \ + boolean_t istate = ml_get_interrupts_enabled(); \ + while (!simple_lock_try(&vcputc_lock)) \ + { \ + if (!istate) \ + handle_pending_TLB_flushes(); \ + cpu_pause(); \ + } \ +MACRO_END + +#define VCPUTC_LOCK_UNLOCK() \ +MACRO_BEGIN \ + simple_unlock(&vcputc_lock); \ +MACRO_END +#else +static hw_lock_data_t vcputc_lock; + +#define VCPUTC_LOCK_INIT() \ +MACRO_BEGIN \ + hw_lock_init(&vcputc_lock); \ +MACRO_END + +#define VCPUTC_LOCK_LOCK() \ +MACRO_BEGIN \ + if (!hw_lock_to(&vcputc_lock, hwLockTimeOut*10))\ + { \ + panic("VCPUTC_LOCK_LOCK"); \ + } \ +MACRO_END + +#define VCPUTC_LOCK_UNLOCK() \ +MACRO_BEGIN \ + hw_lock_unlock(&vcputc_lock); \ +MACRO_END +#endif /* # Attribute codes: @@ -156,18 +218,15 @@ decl_simple_lock_data(,gc_buffer_lock) #define COLOR_CODE_GET(code, fore) (((code) & ((fore) ? 0xF0 : 0x0F)) >> ((fore) ? 4 : 0)) #define COLOR_CODE_SET(code, color, fore) (((code) & ((fore) ? 0x0F : 0xF0)) | ((color) << ((fore) ? 4 : 0))) -static unsigned char gc_color_code = 0; +static unsigned char gc_color_code; /* VT100 state: */ #define MAXPARS 16 -static int gc_x = 0, gc_y = 0, gc_savex, gc_savey; -static int gc_par[MAXPARS], gc_numpars, gc_hanging_cursor, gc_attr, gc_saveattr; +static unsigned int gc_x, gc_y, gc_savex, gc_savey; +static unsigned int gc_par[MAXPARS], gc_numpars, gc_hanging_cursor, gc_attr, gc_saveattr; -/* VT100 tab stops & scroll region */ -static char gc_tab_stops[255]; -static int gc_scrreg_top, gc_scrreg_bottom; - -enum { kProgressAcquireDelay = 5 /* secs */ }; +/* VT100 scroll region */ +static unsigned int gc_scrreg_top, gc_scrreg_bottom; enum vt100state_e { ESnormal, /* Nothing yet */ @@ -184,17 +243,38 @@ enum vt100state_e { ESignore /* Ignore this sequence */ } gc_vt100state = ESnormal; + +#ifdef CONFIG_VC_PROGRESS_WHITE +enum { kProgressAcquireDelay = 0 /* secs */ }; +#else +enum { kProgressAcquireDelay = 5 /* secs */ }; +#endif + +static int8_t vc_rotate_matr[4][2][2] = { + { { 1, 0 }, + { 0, 1 } }, + { { 0, 1 }, + { -1, 0 } }, + { { -1, 0 }, + { 0, -1 } }, + { { 0, -1 }, + { 1, 0 } } +}; + static int gc_wrap_mode = 1, gc_relative_origin = 0; static int gc_charset_select = 0, gc_save_charset_s = 0; static int gc_charset[2] = { 0, 0 }; static int gc_charset_save[2] = { 0, 0 }; -static void gc_clear_line(int xx, int yy, int which); -static void gc_clear_screen(int xx, int yy, int top, int bottom, int which); +static void gc_clear_line(unsigned int xx, unsigned int yy, int which); +static void gc_clear_screen(unsigned int xx, unsigned int yy, int top, + unsigned int bottom, int which); static void gc_enable(boolean_t enable); -static void gc_hide_cursor(int xx, int yy); +static void gc_hide_cursor(unsigned int xx, unsigned int yy); static void gc_initialize(struct vc_info * info); -static void gc_paint_char(int xx, int yy, unsigned char ch, int attrs); +static boolean_t gc_is_tab_stop(unsigned int column); +static void gc_paint_char(unsigned int xx, unsigned int yy, unsigned char ch, + int attrs); static void gc_putchar(char ch); static void gc_putc_askcmd(unsigned char ch); static void gc_putc_charsetcmd(int charset, unsigned char ch); @@ -204,20 +284,19 @@ static void gc_putc_getpars(unsigned char ch); static void gc_putc_gotpars(unsigned char ch); static void gc_putc_normal(unsigned char ch); static void gc_putc_square(unsigned char ch); -static void gc_refresh_screen(void); static void gc_reset_screen(void); static void gc_reset_tabs(void); static void gc_reset_vt100(void); -static void gc_scroll_down(int num, int top, int bottom); -static void gc_scroll_up(int num, int top, int bottom); -static void gc_show_cursor(int xx, int yy); +static void gc_scroll_down(int num, unsigned int top, unsigned int bottom); +static void gc_scroll_up(int num, unsigned int top, unsigned int bottom); +static void gc_set_tab_stop(unsigned int column, boolean_t enabled); +static void gc_show_cursor(unsigned int xx, unsigned int yy); static void gc_update_color(int color, boolean_t fore); -extern int vcputc(int l, int u, int c); static void -gc_clear_line(int xx, int yy, int which) +gc_clear_line(unsigned int xx, unsigned int yy, int which) { - int start, end, i; + unsigned int start, end, i; /* * This routine runs extremely slowly. I don't think it's @@ -239,25 +318,24 @@ gc_clear_line(int xx, int yy, int which) start = 0; end = vinfo.v_columns-1; break; + default: + return; } for (i = start; i <= end; i++) { gc_paint_char(i, yy, ' ', ATTR_NONE); } - } static void -gc_clear_screen(int xx, int yy, int top, int bottom, int which) +gc_clear_screen(unsigned int xx, unsigned int yy, int top, unsigned int bottom, + int which) { - spl_t s; - - s = splhigh(); - simple_lock(&gc_buffer_lock); + if (!gc_buffer_size) return; if ( xx < gc_buffer_columns && yy < gc_buffer_rows && bottom <= gc_buffer_rows ) { - unsigned long start, end; + uint32_t start, end; switch (which) { case 0: /* To end of screen */ @@ -272,65 +350,73 @@ gc_clear_screen(int xx, int yy, int top, int bottom, int which) start = (top * gc_buffer_columns); end = (bottom * gc_buffer_columns) - 1; break; + default: + start = 0; + end = 0; + break; } - memset(gc_buffer_attributes + start, 0x00, end - start + 1); - memset(gc_buffer_characters + start, 0x00, end - start + 1); + memset(gc_buffer_attributes + start, ATTR_NONE, end - start + 1); + memset(gc_buffer_characters + start, ' ', end - start + 1); memset(gc_buffer_colorcodes + start, gc_color_code, end - start + 1); } - simple_unlock(&gc_buffer_lock); - splx(s); - gc_ops.clear_screen(xx, yy, top, bottom, which); } static void gc_enable( boolean_t enable ) { - unsigned char * buffer_attributes; - unsigned char * buffer_characters; - unsigned char * buffer_colorcodes; - unsigned long buffer_columns; - unsigned long buffer_rows; - unsigned long buffer_size; - + unsigned char *buffer_attributes = NULL; + unsigned char *buffer_characters = NULL; + unsigned char *buffer_colorcodes = NULL; + unsigned char *buffer_tab_stops = NULL; + uint32_t buffer_columns = 0; + uint32_t buffer_rows = 0; + uint32_t buffer_size = 0; spl_t s; if ( enable == FALSE ) { - disableConsoleOutput = TRUE; + // only disable console output if it goes to the graphics console + if ( console_is_serial() == FALSE ) + disableConsoleOutput = TRUE; gc_enabled = FALSE; gc_ops.enable(FALSE); } s = splhigh( ); - simple_lock( &gc_buffer_lock ); + VCPUTC_LOCK_LOCK( ); if ( gc_buffer_size ) { buffer_attributes = gc_buffer_attributes; buffer_characters = gc_buffer_characters; buffer_colorcodes = gc_buffer_colorcodes; + buffer_tab_stops = gc_buffer_tab_stops; + buffer_columns = gc_buffer_columns; + buffer_rows = gc_buffer_rows; buffer_size = gc_buffer_size; gc_buffer_attributes = NULL; gc_buffer_characters = NULL; gc_buffer_colorcodes = NULL; + gc_buffer_tab_stops = NULL; gc_buffer_columns = 0; gc_buffer_rows = 0; gc_buffer_size = 0; - simple_unlock( &gc_buffer_lock ); + VCPUTC_LOCK_UNLOCK( ); splx( s ); kfree( buffer_attributes, buffer_size ); kfree( buffer_characters, buffer_size ); kfree( buffer_colorcodes, buffer_size ); + kfree( buffer_tab_stops, buffer_columns ); } else { - simple_unlock( &gc_buffer_lock ); + VCPUTC_LOCK_UNLOCK( ); splx( s ); } @@ -347,14 +433,17 @@ gc_enable( boolean_t enable ) buffer_attributes = (unsigned char *) kalloc( buffer_size ); buffer_characters = (unsigned char *) kalloc( buffer_size ); buffer_colorcodes = (unsigned char *) kalloc( buffer_size ); + buffer_tab_stops = (unsigned char *) kalloc( buffer_columns ); if ( buffer_attributes == NULL || buffer_characters == NULL || - buffer_colorcodes == NULL ) + buffer_colorcodes == NULL || + buffer_tab_stops == NULL ) { if ( buffer_attributes ) kfree( buffer_attributes, buffer_size ); if ( buffer_characters ) kfree( buffer_characters, buffer_size ); if ( buffer_colorcodes ) kfree( buffer_colorcodes, buffer_size ); + if ( buffer_tab_stops ) kfree( buffer_tab_stops, buffer_columns ); buffer_columns = 0; buffer_rows = 0; @@ -362,27 +451,32 @@ gc_enable( boolean_t enable ) } else { - memset( buffer_attributes, 0x00, buffer_size ); - memset( buffer_characters, 0x00, buffer_size ); - memset( buffer_colorcodes, 0x0F, buffer_size ); + memset( buffer_attributes, ATTR_NONE, buffer_size ); + memset( buffer_characters, ' ', buffer_size ); + memset( buffer_colorcodes, COLOR_CODE_SET( 0, COLOR_FOREGROUND, TRUE ), buffer_size ); + memset( buffer_tab_stops, 0, buffer_columns ); } } } s = splhigh( ); - simple_lock( &gc_buffer_lock ); + VCPUTC_LOCK_LOCK( ); gc_buffer_attributes = buffer_attributes; gc_buffer_characters = buffer_characters; gc_buffer_colorcodes = buffer_colorcodes; + gc_buffer_tab_stops = buffer_tab_stops; gc_buffer_columns = buffer_columns; gc_buffer_rows = buffer_rows; gc_buffer_size = buffer_size; - simple_unlock( &gc_buffer_lock ); + gc_reset_screen(); + + VCPUTC_LOCK_UNLOCK( ); splx( s ); - gc_reset_screen(); + gc_ops.clear_screen(gc_x, gc_y, 0, vinfo.v_rows, 2); + gc_ops.show_cursor(gc_x, gc_y); gc_ops.enable(TRUE); gc_enabled = TRUE; @@ -391,24 +485,16 @@ gc_enable( boolean_t enable ) } static void -gc_hide_cursor(int xx, int yy) +gc_hide_cursor(unsigned int xx, unsigned int yy) { - spl_t s; - - s = splhigh(); - simple_lock(&gc_buffer_lock); - if ( xx < gc_buffer_columns && yy < gc_buffer_rows ) { - unsigned long index = (yy * gc_buffer_columns) + xx; + uint32_t index = (yy * gc_buffer_columns) + xx; unsigned char attribute = gc_buffer_attributes[index]; unsigned char character = gc_buffer_characters[index]; unsigned char colorcode = gc_buffer_colorcodes[index]; unsigned char colorcodesave = gc_color_code; - simple_unlock(&gc_buffer_lock); - splx(s); - gc_update_color(COLOR_CODE_GET(colorcode, TRUE ), TRUE ); gc_update_color(COLOR_CODE_GET(colorcode, FALSE), FALSE); @@ -419,9 +505,6 @@ gc_hide_cursor(int xx, int yy) } else { - simple_unlock(&gc_buffer_lock); - splx(s); - gc_ops.hide_cursor(xx, yy); } } @@ -432,7 +515,7 @@ gc_initialize(struct vc_info * info) if ( gc_initialized == FALSE ) { /* Init our lock */ - simple_lock_init(&gc_buffer_lock, 0); + VCPUTC_LOCK_INIT(); gc_initialized = TRUE; } @@ -444,25 +527,17 @@ gc_initialize(struct vc_info * info) } static void -gc_paint_char(int xx, int yy, unsigned char ch, int attrs) +gc_paint_char(unsigned int xx, unsigned int yy, unsigned char ch, int attrs) { - spl_t s; - - s = splhigh(); - simple_lock(&gc_buffer_lock); - if ( xx < gc_buffer_columns && yy < gc_buffer_rows ) { - unsigned long index = (yy * gc_buffer_columns) + xx; + uint32_t index = (yy * gc_buffer_columns) + xx; gc_buffer_attributes[index] = attrs; gc_buffer_characters[index] = ch; gc_buffer_colorcodes[index] = gc_color_code; } - simple_unlock(&gc_buffer_lock); - splx(s); - gc_ops.paint_char(xx, yy, ch, attrs, 0, 0); } @@ -504,18 +579,17 @@ gc_putchar(char ch) } if (gc_x >= vinfo.v_columns) { - gc_x = vinfo.v_columns - 1; - } - if (gc_x < 0) { - gc_x = 0; + if (0 == vinfo.v_columns) + gc_x = 0; + else + gc_x = vinfo.v_columns - 1; } if (gc_y >= vinfo.v_rows) { - gc_y = vinfo.v_rows - 1; - } - if (gc_y < 0) { - gc_y = 0; + if (0 == vinfo.v_rows) + gc_y = 0; + else + gc_y = vinfo.v_rows - 1; } - } static void @@ -572,7 +646,7 @@ gc_putc_charsizecmd(unsigned char ch) break; case '8' : /* fill 'E's */ { - int xx, yy; + unsigned int xx, yy; for (yy = 0; yy < vinfo.v_rows; yy++) for (xx = 0; xx < vinfo.v_columns; xx++) gc_paint_char(xx, yy, 'E', ATTR_NONE); @@ -607,7 +681,7 @@ gc_putc_esc(unsigned char ch) if (ch == 'E') gc_x = 0; break; case 'H': /* Set tab stop */ - gc_tab_stops[gc_x] = 1; + gc_set_tab_stop(gc_x, TRUE); break; case 'M': /* Cursor up */ if (gc_y <= gc_scrreg_top) { @@ -684,7 +758,7 @@ gc_putc_getpars(unsigned char ch) static void gc_putc_gotpars(unsigned char ch) { - int i; + unsigned int i; if (ch < ' ') { /* special case for vttest for handling cursor @@ -711,9 +785,12 @@ gc_putc_gotpars(unsigned char ch) gc_x = vinfo.v_columns-1; break; case 'D': /* Left */ - gc_x -= gc_par[0] ? gc_par[0] : 1; - if (gc_x < 0) + if (gc_par[0] > gc_x) gc_x = 0; + else if (gc_par[0]) + gc_x -= gc_par[0]; + else if (gc_x) + --gc_x; break; case 'H': /* Set cursor position */ case 'f': @@ -725,7 +802,6 @@ gc_putc_gotpars(unsigned char ch) break; case 'X': /* clear p1 characters */ if (gc_numpars) { - int i; for (i = gc_x; i < gc_x + gc_par[0]; i++) gc_paint_char(i, gc_y, ' ', ATTR_NONE); } @@ -744,14 +820,12 @@ gc_putc_gotpars(unsigned char ch) break; case 3: /* Clear every tabs */ { - int i; - for (i = 0; i <= vinfo.v_columns; i++) - gc_tab_stops[i] = 0; + gc_set_tab_stop(i, FALSE); } break; case 0: - gc_tab_stops[gc_x] = 0; + gc_set_tab_stop(gc_x, FALSE); break; } break; @@ -798,8 +872,6 @@ gc_putc_gotpars(unsigned char ch) /* ensure top < bottom, and both within limits */ if ((gc_numpars > 0) && (gc_par[0] < vinfo.v_rows)) { gc_scrreg_top = gc_par[0] ? gc_par[0] - 1 : 0; - if (gc_scrreg_top < 0) - gc_scrreg_top = 0; } else { gc_scrreg_top = 0; } @@ -833,7 +905,8 @@ gc_putc_normal(unsigned char ch) } break; case '\t': /* Tab */ - while (gc_x < vinfo.v_columns && !gc_tab_stops[++gc_x]); + if (gc_buffer_tab_stops) while (gc_x < vinfo.v_columns && !gc_is_tab_stop(++gc_x)); + if (gc_x >= vinfo.v_columns) gc_x = vinfo.v_columns-1; break; @@ -906,64 +979,42 @@ gc_putc_square(unsigned char ch) } -static void -gc_refresh_screen(void) -{ - spl_t s; - - s = splhigh(); - simple_lock(&gc_buffer_lock); - - if ( gc_buffer_size ) - { - unsigned char colorcodesave = gc_color_code; - unsigned long column, row; - unsigned long index; - - for ( index = 0, row = 0 ; row < gc_buffer_rows ; row++ ) - { - for ( column = 0 ; column < gc_buffer_columns ; index++, column++ ) - { - if ( gc_buffer_colorcodes[index] != gc_color_code ) - { - gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes[index], TRUE ), TRUE ); - gc_update_color(COLOR_CODE_GET(gc_buffer_colorcodes[index], FALSE), FALSE); - } - - gc_ops.paint_char(column, row, gc_buffer_characters[index], gc_buffer_attributes[index], 0, 0); - } - } - - if ( colorcodesave != gc_color_code ) - { - gc_update_color(COLOR_CODE_GET(colorcodesave, TRUE ), TRUE ); - gc_update_color(COLOR_CODE_GET(colorcodesave, FALSE), FALSE); - } - } - - simple_unlock(&gc_buffer_lock); - splx(s); -} - static void gc_reset_screen(void) { - gc_hide_cursor(gc_x, gc_y); gc_reset_vt100(); gc_x = gc_y = 0; - gc_clear_screen(gc_x, gc_y, 0, vinfo.v_rows, 2); - gc_show_cursor(gc_x, gc_y); } static void gc_reset_tabs(void) { - int i; + unsigned int i; + + if (!gc_buffer_tab_stops) return; + + for (i = 0; i < vinfo.v_columns; i++) { + gc_buffer_tab_stops[i] = ((i % 8) == 0); + } + +} - for (i = 0; i<= vinfo.v_columns; i++) { - gc_tab_stops[i] = ((i % 8) == 0); +static void +gc_set_tab_stop(unsigned int column, boolean_t enabled) +{ + if (gc_buffer_tab_stops && (column < vinfo.v_columns)) { + gc_buffer_tab_stops[column] = enabled; } +} +static boolean_t gc_is_tab_stop(unsigned int column) +{ + if (gc_buffer_tab_stops == NULL) + return ((column % 8) == 0); + if (column < vinfo.v_columns) + return gc_buffer_tab_stops[column]; + else + return FALSE; } static void @@ -982,18 +1033,15 @@ gc_reset_vt100(void) } static void -gc_scroll_down(int num, int top, int bottom) +gc_scroll_down(int num, unsigned int top, unsigned int bottom) { - spl_t s; - - s = splhigh(); - simple_lock(&gc_buffer_lock); + if (!gc_buffer_size) return; if ( bottom <= gc_buffer_rows ) { unsigned char colorcodesave = gc_color_code; - unsigned long column, row; - unsigned long index, jump; + uint32_t column, row; + uint32_t index, jump; jump = num * gc_buffer_columns; @@ -1045,35 +1093,64 @@ gc_scroll_down(int num, int top, int bottom) gc_update_color(COLOR_CODE_GET(colorcodesave, FALSE), FALSE); } - simple_unlock(&gc_buffer_lock); - splx(s); + /* Now set the freed up lines to the background colour */ + + for ( row = top ; row < top + num ; row++ ) + { + index = row * gc_buffer_columns; + + for ( column = 0 ; column < gc_buffer_columns ; index++, column++ ) + { + if ( gc_buffer_attributes[index] != ATTR_NONE || + gc_buffer_characters[index] != ' ' || + gc_buffer_colorcodes[index] != gc_color_code ) + { + if ( gc_buffer_colorcodes[index] != gc_color_code ) + { + gc_ops.paint_char( /* xx */ column, + /* yy */ row, + /* ch */ ' ', + /* attrs */ ATTR_NONE, + /* ch_previous */ 0, + /* attrs_previous */ 0 ); + } + else + { + gc_ops.paint_char( /* xx */ column, + /* yy */ row, + /* ch */ ' ', + /* attrs */ ATTR_NONE, + /* ch_previous */ gc_buffer_characters[index], + /* attrs_previous */ gc_buffer_attributes[index] ); + } + + gc_buffer_attributes[index] = ATTR_NONE; + gc_buffer_characters[index] = ' '; + gc_buffer_colorcodes[index] = gc_color_code; + } + } + } } else { - simple_unlock(&gc_buffer_lock); - splx(s); - gc_ops.scroll_down(num, top, bottom); - } - /* Now set the freed up lines to the background colour */ + /* Now set the freed up lines to the background colour */ - gc_clear_screen(vinfo.v_columns - 1, top + num - 1, top, bottom, 1); + gc_clear_screen(vinfo.v_columns - 1, top + num - 1, top, bottom, 1); + } } static void -gc_scroll_up(int num, int top, int bottom) +gc_scroll_up(int num, unsigned int top, unsigned int bottom) { - spl_t s; - - s = splhigh(); - simple_lock(&gc_buffer_lock); + if (!gc_buffer_size) return; if ( bottom <= gc_buffer_rows ) { unsigned char colorcodesave = gc_color_code; - unsigned long column, row; - unsigned long index, jump; + uint32_t column, row; + uint32_t index, jump; jump = num * gc_buffer_columns; @@ -1115,7 +1192,6 @@ gc_scroll_up(int num, int top, int bottom) gc_buffer_attributes[index] = gc_buffer_attributes[index + jump]; gc_buffer_characters[index] = gc_buffer_characters[index + jump]; gc_buffer_colorcodes[index] = gc_buffer_colorcodes[index + jump]; - } } } @@ -1126,41 +1202,65 @@ gc_scroll_up(int num, int top, int bottom) gc_update_color(COLOR_CODE_GET(colorcodesave, FALSE), FALSE); } - simple_unlock(&gc_buffer_lock); - splx(s); + /* Now set the freed up lines to the background colour */ + + for ( row = bottom - num ; row < bottom ; row++ ) + { + index = row * gc_buffer_columns; + + for ( column = 0 ; column < gc_buffer_columns ; index++, column++ ) + { + if ( gc_buffer_attributes[index] != ATTR_NONE || + gc_buffer_characters[index] != ' ' || + gc_buffer_colorcodes[index] != gc_color_code ) + { + if ( gc_buffer_colorcodes[index] != gc_color_code ) + { + gc_ops.paint_char( /* xx */ column, + /* yy */ row, + /* ch */ ' ', + /* attrs */ ATTR_NONE, + /* ch_previous */ 0, + /* attrs_previous */ 0 ); + } + else + { + gc_ops.paint_char( /* xx */ column, + /* yy */ row, + /* ch */ ' ', + /* attrs */ ATTR_NONE, + /* ch_previous */ gc_buffer_characters[index], + /* attrs_previous */ gc_buffer_attributes[index] ); + } + + gc_buffer_attributes[index] = ATTR_NONE; + gc_buffer_characters[index] = ' '; + gc_buffer_colorcodes[index] = gc_color_code; + } + } + } } else { - simple_unlock(&gc_buffer_lock); - splx(s); - gc_ops.scroll_up(num, top, bottom); - } - /* Now set the freed up lines to the background colour */ + /* Now set the freed up lines to the background colour */ - gc_clear_screen(0, bottom - num, top, bottom, 0); + gc_clear_screen(0, bottom - num, top, bottom, 0); + } } static void -gc_show_cursor(int xx, int yy) +gc_show_cursor(unsigned int xx, unsigned int yy) { - spl_t s; - - s = splhigh(); - simple_lock(&gc_buffer_lock); - if ( xx < gc_buffer_columns && yy < gc_buffer_rows ) { - unsigned long index = (yy * gc_buffer_columns) + xx; + uint32_t index = (yy * gc_buffer_columns) + xx; unsigned char attribute = gc_buffer_attributes[index]; unsigned char character = gc_buffer_characters[index]; unsigned char colorcode = gc_buffer_colorcodes[index]; unsigned char colorcodesave = gc_color_code; - simple_unlock(&gc_buffer_lock); - splx(s); - gc_update_color(COLOR_CODE_GET(colorcode, FALSE), TRUE ); gc_update_color(COLOR_CODE_GET(colorcode, TRUE ), FALSE); @@ -1171,9 +1271,6 @@ gc_show_cursor(int xx, int yy) } else { - simple_unlock(&gc_buffer_lock); - splx(s); - gc_ops.show_cursor(xx, yy); } } @@ -1181,21 +1278,36 @@ gc_show_cursor(int xx, int yy) static void gc_update_color(int color, boolean_t fore) { + assert(gc_ops.update_color); + gc_color_code = COLOR_CODE_SET(gc_color_code, color, fore); gc_ops.update_color(color, fore); } -int -vcputc(int l, int u, int c) +void +vcputc(__unused int l, __unused int u, int c) { - if ( gc_enabled || debug_mode ) - { - gc_hide_cursor(gc_x, gc_y); - gc_putchar(c); - gc_show_cursor(gc_x, gc_y); - } + if ( gc_initialized && ( gc_enabled || debug_mode ) ) + { + spl_t s; - return 0; + s = splhigh(); +#if defined(__i386__) || defined(__x86_64__) + x86_filter_TLB_coherency_interrupts(TRUE); +#endif + VCPUTC_LOCK_LOCK(); + if ( gc_enabled || debug_mode ) + { + gc_hide_cursor(gc_x, gc_y); + gc_putchar(c); + gc_show_cursor(gc_x, gc_y); + } + VCPUTC_LOCK_UNLOCK(); +#if defined(__i386__) || defined(__x86_64__) + x86_filter_TLB_coherency_interrupts(FALSE); +#endif + splx(s); + } } /* @@ -1208,22 +1320,22 @@ vcputc(int l, int u, int c) */ static unsigned char vc_color_index_table[33] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }; - -static unsigned long vc_colors[8][3] = { - { 0xFFFFFFFF, 0x00000000, 0x00000000 }, /* black */ - { 0x23232323, 0x7C007C00, 0x00FF0000 }, /* red */ - { 0xb9b9b9b9, 0x03e003e0, 0x0000FF00 }, /* green */ - { 0x05050505, 0x7FE07FE0, 0x00FFFF00 }, /* yellow */ - { 0xd2d2d2d2, 0x001f001f, 0x000000FF}, /* blue */ -// { 0x80808080, 0x31933193, 0x00666699 }, /* blue */ - { 0x18181818, 0x7C1F7C1F, 0x00FF00FF }, /* magenta */ - { 0xb4b4b4b4, 0x03FF03FF, 0x0000FFFF }, /* cyan */ - { 0x00000000, 0x7FFF7FFF, 0x00FFFFFF } /* white */ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 2 }; + +static uint32_t vc_colors[8][4] = { + { 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000 }, /* black */ + { 0x23232323, 0x7C007C00, 0x00FF0000, 0x3FF00000 }, /* red */ + { 0xb9b9b9b9, 0x03e003e0, 0x0000FF00, 0x000FFC00 }, /* green */ + { 0x05050505, 0x7FE07FE0, 0x00FFFF00, 0x3FFFFC00 }, /* yellow */ + { 0xd2d2d2d2, 0x001f001f, 0x000000FF, 0x000003FF }, /* blue */ +// { 0x80808080, 0x31933193, 0x00666699, 0x00000000 }, /* blue */ + { 0x18181818, 0x7C1F7C1F, 0x00FF00FF, 0x3FF003FF }, /* magenta */ + { 0xb4b4b4b4, 0x03FF03FF, 0x0000FFFF, 0x000FFFFF }, /* cyan */ + { 0x00000000, 0x7FFF7FFF, 0x00FFFFFF, 0x3FFFFFFF } /* white */ }; -static unsigned long vc_color_fore = 0; -static unsigned long vc_color_back = 0; +static uint32_t vc_color_fore = 0; +static uint32_t vc_color_back = 0; /* * New Rendering code from Michel Pollet @@ -1233,7 +1345,7 @@ static unsigned long vc_color_back = 0; static unsigned char *vc_rendered_font = NULL; /* Rendered Font Size */ -static unsigned long vc_rendered_font_size = 0; +static uint32_t vc_rendered_font_size = 0; /* Size of a character in the table (bytes) */ static int vc_rendered_char_size = 0; @@ -1241,24 +1353,11 @@ static int vc_rendered_char_size = 0; #define REN_MAX_DEPTH 32 static unsigned char vc_rendered_char[ISO_CHAR_HEIGHT * ((REN_MAX_DEPTH / 8) * ISO_CHAR_WIDTH)]; -static void vc_clear_screen(int xx, int yy, int scrreg_top, int scrreg_bottom, int which); -static void vc_enable(boolean_t enable); -static void vc_initialize(struct vc_info * vinfo_p); -static void vc_paint_char(int xx, int yy, unsigned char ch, int attrs, unsigned char ch_previous, int attrs_previous); -static void vc_paint_char_8(int xx, int yy, unsigned char ch, int attrs, unsigned char ch_previous, int attrs_previous); -static void vc_paint_char_16(int xx, int yy, unsigned char ch, int attrs, unsigned char ch_previous, int attrs_previous); -static void vc_paint_char_32(int xx, int yy, unsigned char ch, int attrs, unsigned char ch_previous, int attrs_previous); -static void vc_render_char(unsigned char ch, unsigned char *renderptr, short newdepth); -static void vc_render_font(short newdepth); -static void vc_reverse_cursor(int xx, int yy); -static void vc_scroll_down(int num, int scrreg_top, int scrreg_bottom); -static void vc_scroll_up(int num, int scrreg_top, int scrreg_bottom); -static void vc_update_color(int color, boolean_t fore); - static void -vc_clear_screen(int xx, int yy, int scrreg_top, int scrreg_bottom, int which) +vc_clear_screen(unsigned int xx, unsigned int yy, unsigned int scrreg_top, + unsigned int scrreg_bottom, int which) { - unsigned long *p, *endp, *row; + uint32_t *p, *endp, *row; int linelongs, col; int rowline, rowlongs; @@ -1269,8 +1368,8 @@ vc_clear_screen(int xx, int yy, int scrreg_top, int scrreg_bottom, int which) rowline = vinfo.v_rowscanbytes >> 2; rowlongs = vinfo.v_rowbytes >> 2; - p = (unsigned long*) vinfo.v_baseaddr; - endp = (unsigned long*) vinfo.v_baseaddr; + p = (uint32_t*) vinfo.v_baseaddr; + endp = (uint32_t*) vinfo.v_baseaddr; switch (which) { case 0: /* To end of screen */ @@ -1304,73 +1403,74 @@ vc_clear_screen(int xx, int yy, int scrreg_top, int scrreg_bottom, int which) } static void -vc_enable(boolean_t enable) +vc_render_char(unsigned char ch, unsigned char *renderptr, short newdepth) { - if ( enable ) - { - vc_render_font(vinfo.v_depth); - } -} + union { + unsigned char *charptr; + unsigned short *shortptr; + uint32_t *longptr; + } current; /* current place in rendered font, multiple types. */ + unsigned char *theChar; /* current char in iso_font */ + int line; -static void -vc_initialize(struct vc_info * vinfo_p) -{ - vinfo.v_rows = vinfo.v_height / ISO_CHAR_HEIGHT; - vinfo.v_columns = vinfo.v_width / ISO_CHAR_WIDTH; - vinfo.v_rowscanbytes = (vinfo.v_depth / 8) * vinfo.v_width; -} + current.charptr = renderptr; + theChar = iso_font + (ch * ISO_CHAR_HEIGHT); -static void -vc_paint_char(int xx, int yy, unsigned char ch, int attrs, unsigned char ch_previous, int attrs_previous) -{ - if( !vinfo.v_depth) - return; + for (line = 0; line < ISO_CHAR_HEIGHT; line++) { + unsigned char mask = 1; + do { + switch (newdepth) { + case 8: + *current.charptr++ = (*theChar & mask) ? 0xFF : 0; + break; + case 16: + *current.shortptr++ = (*theChar & mask) ? 0xFFFF : 0; + break; - switch( vinfo.v_depth) { - case 8: - vc_paint_char_8(xx, yy, ch, attrs, ch_previous, attrs_previous); - break; - case 16: - vc_paint_char_16(xx, yy, ch, attrs, ch_previous, attrs_previous); - break; - case 32: - vc_paint_char_32(xx, yy, ch, attrs, ch_previous, attrs_previous); - break; + case 30: + case 32: + *current.longptr++ = (*theChar & mask) ? 0xFFFFFFFF : 0; + break; + } + mask <<= 1; + } while (mask); /* while the single bit drops to the right */ + theChar++; } } static void -vc_paint_char_8(int xx, int yy, unsigned char ch, int attrs, unsigned char ch_previous, int attrs_previous) +vc_paint_char_8(unsigned int xx, unsigned int yy, unsigned char ch, int attrs, + __unused unsigned char ch_previous, __unused int attrs_previous) { - unsigned long *theChar; - unsigned long *where; + uint32_t *theChar; + uint32_t *where; int i; if (vc_rendered_font) { - theChar = (unsigned long*)(vc_rendered_font + (ch * vc_rendered_char_size)); + theChar = (uint32_t*)(vc_rendered_font + (ch * vc_rendered_char_size)); } else { vc_render_char(ch, vc_rendered_char, 8); - theChar = (unsigned long*)(vc_rendered_char); + theChar = (uint32_t*)(vc_rendered_char); } - where = (unsigned long*)(vinfo.v_baseaddr + + where = (uint32_t*)(vinfo.v_baseaddr + (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) + (xx * ISO_CHAR_WIDTH)); if (!attrs) for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* No attr? FLY !*/ - unsigned long *store = where; + uint32_t *store = where; int x; for (x = 0; x < 2; x++) { - unsigned long val = *theChar++; + uint32_t val = *theChar++; val = (vc_color_back & ~val) | (vc_color_fore & val); *store++ = val; } - where = (unsigned long*)(((unsigned char*)where)+vinfo.v_rowbytes); + where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes); } else for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* a little slower */ - unsigned long *store = where, lastpixel = 0; + uint32_t *store = where, lastpixel = 0; int x; for (x = 0 ; x < 2; x++) { - unsigned long val = *theChar++, save = val; + uint32_t val = *theChar++, save = val; if (attrs & ATTR_BOLD) { /* bold support */ if (lastpixel && !(save & 0xFF000000)) val |= 0xff000000; @@ -1389,43 +1489,45 @@ vc_paint_char_8(int xx, int yy, unsigned char ch, int attrs, unsigned char ch_pr lastpixel = save & 0xff; } - where = (unsigned long*)(((unsigned char*)where)+vinfo.v_rowbytes); + where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes); } } static void -vc_paint_char_16(int xx, int yy, unsigned char ch, int attrs, unsigned char ch_previous, int attrs_previous) +vc_paint_char_16(unsigned int xx, unsigned int yy, unsigned char ch, int attrs, + __unused unsigned char ch_previous, + __unused int attrs_previous) { - unsigned long *theChar; - unsigned long *where; + uint32_t *theChar; + uint32_t *where; int i; if (vc_rendered_font) { - theChar = (unsigned long*)(vc_rendered_font + (ch * vc_rendered_char_size)); + theChar = (uint32_t*)(vc_rendered_font + (ch * vc_rendered_char_size)); } else { vc_render_char(ch, vc_rendered_char, 16); - theChar = (unsigned long*)(vc_rendered_char); + theChar = (uint32_t*)(vc_rendered_char); } - where = (unsigned long*)(vinfo.v_baseaddr + + where = (uint32_t*)(vinfo.v_baseaddr + (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) + (xx * ISO_CHAR_WIDTH * 2)); if (!attrs) for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* No attrs ? FLY ! */ - unsigned long *store = where; + uint32_t *store = where; int x; for (x = 0; x < 4; x++) { - unsigned long val = *theChar++; + uint32_t val = *theChar++; val = (vc_color_back & ~val) | (vc_color_fore & val); *store++ = val; } - where = (unsigned long*)(((unsigned char*)where)+vinfo.v_rowbytes); + where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes); } else for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* a little bit slower */ - unsigned long *store = where, lastpixel = 0; + uint32_t *store = where, lastpixel = 0; int x; for (x = 0 ; x < 4; x++) { - unsigned long val = *theChar++, save = val; + uint32_t val = *theChar++, save = val; if (attrs & ATTR_BOLD) { /* bold support */ if (save == 0xFFFF0000) val |= 0xFFFF; else if (lastpixel && !(save & 0xFFFF0000)) @@ -1440,25 +1542,26 @@ vc_paint_char_16(int xx, int yy, unsigned char ch, int attrs, unsigned char ch_p lastpixel = save & 0x7fff; } - where = (unsigned long*)(((unsigned char*)where)+vinfo.v_rowbytes); + where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes); } } static void -vc_paint_char_32(int xx, int yy, unsigned char ch, int attrs, unsigned char ch_previous, int attrs_previous) +vc_paint_char_32(unsigned int xx, unsigned int yy, unsigned char ch, int attrs, + unsigned char ch_previous, int attrs_previous) { - unsigned long *theChar; - unsigned long *theCharPrevious; - unsigned long *where; + uint32_t *theChar; + uint32_t *theCharPrevious; + uint32_t *where; int i; if (vc_rendered_font) { - theChar = (unsigned long*)(vc_rendered_font + (ch * vc_rendered_char_size)); - theCharPrevious = (unsigned long*)(vc_rendered_font + (ch_previous * vc_rendered_char_size)); + theChar = (uint32_t*)(vc_rendered_font + (ch * vc_rendered_char_size)); + theCharPrevious = (uint32_t*)(vc_rendered_font + (ch_previous * vc_rendered_char_size)); } else { vc_render_char(ch, vc_rendered_char, 32); - theChar = (unsigned long*)(vc_rendered_char); + theChar = (uint32_t*)(vc_rendered_char); theCharPrevious = NULL; } if (!ch_previous) { @@ -1467,15 +1570,15 @@ vc_paint_char_32(int xx, int yy, unsigned char ch, int attrs, unsigned char ch_p if (attrs_previous) { theCharPrevious = NULL; } - where = (unsigned long*)(vinfo.v_baseaddr + + where = (uint32_t*)(vinfo.v_baseaddr + (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) + (xx * ISO_CHAR_WIDTH * 4)); if (!attrs) for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* No attrs ? FLY ! */ - unsigned long *store = where; + uint32_t *store = where; int x; for (x = 0; x < 8; x++) { - unsigned long val = *theChar++; + uint32_t val = *theChar++; if (theCharPrevious == NULL || val != *theCharPrevious++ ) { val = (vc_color_back & ~val) | (vc_color_fore & val); *store++ = val; @@ -1484,12 +1587,12 @@ vc_paint_char_32(int xx, int yy, unsigned char ch, int attrs, unsigned char ch_p } } - where = (unsigned long*)(((unsigned char*)where)+vinfo.v_rowbytes); + where = (uint32_t *)(((unsigned char*)where)+vinfo.v_rowbytes); } else for (i = 0; i < ISO_CHAR_HEIGHT; i++) { /* a little slower */ - unsigned long *store = where, lastpixel = 0; + uint32_t *store = where, lastpixel = 0; int x; for (x = 0 ; x < 8; x++) { - unsigned long val = *theChar++, save = val; + uint32_t val = *theChar++, save = val; if (attrs & ATTR_BOLD) { /* bold support */ if (lastpixel && !save) val = 0xFFFFFFFF; @@ -1502,45 +1605,31 @@ vc_paint_char_32(int xx, int yy, unsigned char ch, int attrs, unsigned char ch_p lastpixel = save; } - where = (unsigned long*)(((unsigned char*)where)+vinfo.v_rowbytes); + where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes); } } static void -vc_render_char(unsigned char ch, unsigned char *renderptr, short newdepth) +vc_paint_char(unsigned int xx, unsigned int yy, unsigned char ch, int attrs, + unsigned char ch_previous, int attrs_previous) { - union { - unsigned char *charptr; - unsigned short *shortptr; - unsigned long *longptr; - } current; /* current place in rendered font, multiple types. */ - - unsigned char *theChar; /* current char in iso_font */ - - int line; - - current.charptr = renderptr; - theChar = iso_font + (ch * ISO_CHAR_HEIGHT); + if(!vinfo.v_depth) + return; - for (line = 0; line < ISO_CHAR_HEIGHT; line++) { - unsigned char mask = 1; - do { - switch (newdepth) { - case 8: - *current.charptr++ = (*theChar & mask) ? 0xFF : 0; - break; - case 16: - *current.shortptr++ = (*theChar & mask) ? 0xFFFF : 0; - break; - - case 32: - *current.longptr++ = (*theChar & mask) ? 0xFFFFFFFF : 0; - break; - } - mask <<= 1; - } while (mask); /* while the single bit drops to the right */ - theChar++; + switch(vinfo.v_depth) { + case 8: + vc_paint_char_8(xx, yy, ch, attrs, ch_previous, attrs_previous); + break; + case 16: + vc_paint_char_16(xx, yy, ch, attrs, ch_previous, + attrs_previous); + break; + case 30: + case 32: + vc_paint_char_32(xx, yy, ch, attrs, ch_previous, + attrs_previous); + break; } } @@ -1550,6 +1639,10 @@ vc_render_font(short newdepth) static short olddepth = 0; int charindex; /* index in ISO font */ + unsigned char *rendered_font; + unsigned int rendered_font_size; + int rendered_char_size; + spl_t s; if (vm_initialized == FALSE) { return; /* nothing to do */ @@ -1557,36 +1650,69 @@ vc_render_font(short newdepth) if (olddepth == newdepth && vc_rendered_font) { return; /* nothing to do */ } - if (vc_rendered_font) { - kfree(vc_rendered_font, vc_rendered_font_size); + + s = splhigh(); + VCPUTC_LOCK_LOCK(); + + rendered_font = vc_rendered_font; + rendered_font_size = vc_rendered_font_size; + rendered_char_size = vc_rendered_char_size; + + vc_rendered_font = NULL; + vc_rendered_font_size = 0; + vc_rendered_char_size = 0; + + VCPUTC_LOCK_UNLOCK(); + splx(s); + + if (rendered_font) { + kfree(rendered_font, rendered_font_size); + rendered_font = NULL; } - vc_rendered_char_size = ISO_CHAR_HEIGHT * ((newdepth / 8) * ISO_CHAR_WIDTH); - vc_rendered_font_size = (ISO_CHAR_MAX-ISO_CHAR_MIN+1) * vc_rendered_char_size; - vc_rendered_font = (unsigned char *) kalloc(vc_rendered_font_size); + if (newdepth) { + rendered_char_size = ISO_CHAR_HEIGHT * (((newdepth + 7) / 8) * ISO_CHAR_WIDTH); + rendered_font_size = (ISO_CHAR_MAX-ISO_CHAR_MIN+1) * rendered_char_size; + rendered_font = (unsigned char *) kalloc(rendered_font_size); + } - if (vc_rendered_font == NULL) { - vc_rendered_font_size = 0; + if (rendered_font == NULL) { return; } for (charindex = ISO_CHAR_MIN; charindex <= ISO_CHAR_MAX; charindex++) { - vc_render_char(charindex, vc_rendered_font + (charindex * vc_rendered_char_size), newdepth); + vc_render_char(charindex, rendered_font + (charindex * rendered_char_size), newdepth); } olddepth = newdepth; + + s = splhigh(); + VCPUTC_LOCK_LOCK(); + + vc_rendered_font = rendered_font; + vc_rendered_font_size = rendered_font_size; + vc_rendered_char_size = rendered_char_size; + + VCPUTC_LOCK_UNLOCK(); + splx(s); } static void -vc_reverse_cursor(int xx, int yy) +vc_enable(boolean_t enable) +{ + vc_render_font(enable ? vinfo.v_depth : 0); +} + +static void +vc_reverse_cursor(unsigned int xx, unsigned int yy) { - unsigned long *where; + uint32_t *where; int line, col; if(!vinfo.v_depth) return; - where = (unsigned long*)(vinfo.v_baseaddr + + where = (uint32_t*)(vinfo.v_baseaddr + (yy * ISO_CHAR_HEIGHT * vinfo.v_rowbytes) + (xx /** ISO_CHAR_WIDTH*/ * vinfo.v_depth)); for (line = 0; line < ISO_CHAR_HEIGHT; line++) { @@ -1604,14 +1730,14 @@ vc_reverse_cursor(int xx, int yy) where[col] = ~where[col]; break; } - where = (unsigned long*)(((unsigned char*)where)+vinfo.v_rowbytes); + where = (uint32_t*)(((unsigned char*)where)+vinfo.v_rowbytes); } } static void -vc_scroll_down(int num, int scrreg_top, int scrreg_bottom) +vc_scroll_down(int num, unsigned int scrreg_top, unsigned int scrreg_bottom) { - unsigned long *from, *to, linelongs, i, line, rowline, rowscanline; + uint32_t *from, *to, linelongs, i, line, rowline, rowscanline; if(!vinfo.v_depth) return; @@ -1620,7 +1746,7 @@ vc_scroll_down(int num, int scrreg_top, int scrreg_bottom) rowline = vinfo.v_rowbytes >> 2; rowscanline = vinfo.v_rowscanbytes >> 2; - to = (unsigned long *) vinfo.v_baseaddr + (linelongs * scrreg_bottom) + to = (uint32_t *) vinfo.v_baseaddr + (linelongs * scrreg_bottom) - (rowline - rowscanline); from = to - (linelongs * num); /* handle multiple line scroll (Michel Pollet) */ @@ -1631,9 +1757,9 @@ vc_scroll_down(int num, int scrreg_top, int scrreg_bottom) /* * Only copy what is displayed */ - video_scroll_down((unsigned int) from, - (unsigned int) (from-(vinfo.v_rowscanbytes >> 2)), - (unsigned int) to); + video_scroll_down(from, + (from-(vinfo.v_rowscanbytes >> 2)), + to); from -= rowline; to -= rowline; @@ -1642,9 +1768,9 @@ vc_scroll_down(int num, int scrreg_top, int scrreg_bottom) } static void -vc_scroll_up(int num, int scrreg_top, int scrreg_bottom) +vc_scroll_up(int num, unsigned int scrreg_top, unsigned int scrreg_bottom) { - unsigned long *from, *to, linelongs, i, line, rowline, rowscanline; + uint32_t *from, *to, linelongs, i, line, rowline, rowscanline; if(!vinfo.v_depth) return; @@ -1653,7 +1779,7 @@ vc_scroll_up(int num, int scrreg_top, int scrreg_bottom) rowline = vinfo.v_rowbytes >> 2; rowscanline = vinfo.v_rowscanbytes >> 2; - to = (unsigned long *) vinfo.v_baseaddr + (scrreg_top * linelongs); + to = (uint32_t *) vinfo.v_baseaddr + (scrreg_top * linelongs); from = to + (linelongs * num); /* handle multiple line scroll (Michel Pollet) */ i = (scrreg_bottom - scrreg_top) - num; @@ -1663,9 +1789,9 @@ vc_scroll_up(int num, int scrreg_top, int scrreg_bottom) /* * Only copy what is displayed */ - video_scroll_up((unsigned int) from, - (unsigned int) (from+(vinfo.v_rowscanbytes >> 2)), - (unsigned int) to); + video_scroll_up(from, + (from+(vinfo.v_rowscanbytes >> 2)), + to); from += rowline; to += rowline; @@ -1690,60 +1816,74 @@ vc_update_color(int color, boolean_t fore) * -------------------------------------- */ -struct vc_progress_element { - unsigned int version; - unsigned int flags; - unsigned int time; - unsigned char count; - unsigned char res[3]; - int width; - int height; - int dx; - int dy; - int transparent; - unsigned int res2[3]; - unsigned char data[0]; -}; -typedef struct vc_progress_element vc_progress_element; - static vc_progress_element * vc_progress; -static const unsigned char * vc_progress_data; +static const unsigned char * vc_progress_data[2]; static const unsigned char * vc_progress_alpha; static boolean_t vc_progress_enable; static const unsigned char * vc_clut; static const unsigned char * vc_clut8; static unsigned char vc_revclut8[256]; static uint32_t vc_progress_interval; +static uint32_t vc_progress_count; +static uint32_t vc_progress_angle; static uint64_t vc_progress_deadline; static thread_call_data_t vc_progress_call; static boolean_t vc_needsave; static void * vc_saveunder; static vm_size_t vc_saveunder_len; +static int8_t vc_uiselect = 0; decl_simple_lock_data(,vc_progress_lock) -static void vc_blit_rect( int x, int y, int width, int height, - const unsigned char * dataPtr, const unsigned char * alphaPtr, - void * backBuffer, boolean_t save, boolean_t static_alpha ); -static void vc_blit_rect_8( int x, int y, int width, int height, - const unsigned char * dataPtr, const unsigned char * alphaPtr, - unsigned char * backBuffer, boolean_t save, boolean_t static_alpha ); -static void vc_blit_rect_16( int x, int y, int width, int height, - const unsigned char * dataPtr, const unsigned char * alphaPtr, - unsigned short * backBuffer, boolean_t save, boolean_t static_alpha ); -static void vc_blit_rect_32( int x, int y, int width, int height, - const unsigned char * dataPtr, const unsigned char * alphaPtr, - unsigned int * backBuffer, boolean_t save, boolean_t static_alpha ); -extern void vc_display_icon( vc_progress_element * desc, const unsigned char * data ); -extern void vc_progress_initialize( vc_progress_element * desc, const unsigned char * data, const unsigned char * clut ); -static void vc_progress_set( boolean_t enable, uint32_t delay ); +enum { + kSave = 0x10, + kDataIndexed = 0x20, + kDataAlpha = 0x40, + kDataBack = 0x80, + kDataRotate = 0x03, + kDataRotate0 = 0, + kDataRotate90 = 1, + kDataRotate180 = 2, + kDataRotate270 = 3 +}; + +static void vc_blit_rect(int x, int y, int bx, + int width, int height, + int sourceRow, int backRow, + const unsigned char * dataPtr, + void * backBuffer, + unsigned int flags); +static void vc_blit_rect_8(int x, int y, int bx, + int width, int height, + int sourceRow, int backRow, + const unsigned char * dataPtr, + unsigned char * backBuffer, + unsigned int flags); +static void vc_blit_rect_16(int x, int y, int bx, + int width, int height, + int sourceRow, int backRow, + const unsigned char * dataPtr, + unsigned short * backBuffer, + unsigned int flags); +static void vc_blit_rect_32(int x, int y, int bx, + int width, int height, + int sourceRow, int backRow, + const unsigned char * dataPtr, + unsigned int * backBuffer, + unsigned int flags); +static void vc_blit_rect_30(int x, int y, int bx, + int width, int height, + int sourceRow, int backRow, + const unsigned char * dataPtr, + unsigned int * backBuffer, + unsigned int flags); static void vc_progress_task( void * arg0, void * arg ); -static void vc_blit_rect( int x, int y, - int width, int height, - const unsigned char * dataPtr, - const unsigned char * alphaPtr, - void * backBuffer, - boolean_t save, boolean_t static_alpha ) +static void vc_blit_rect(int x, int y, int bx, + int width, int height, + int sourceRow, int backRow, + const unsigned char * dataPtr, + void * backBuffer, + unsigned int flags) { if(!vinfo.v_depth) return; @@ -1751,177 +1891,421 @@ static void vc_blit_rect( int x, int y, switch( vinfo.v_depth) { case 8: if( vc_clut8 == vc_clut) - vc_blit_rect_8( x, y, width, height, dataPtr, alphaPtr, (unsigned char *) backBuffer, save, static_alpha ); + vc_blit_rect_8( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned char *) backBuffer, flags ); break; case 16: - vc_blit_rect_16( x, y, width, height, dataPtr, alphaPtr, (unsigned short *) backBuffer, save, static_alpha ); + vc_blit_rect_16( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned short *) backBuffer, flags ); break; case 32: - vc_blit_rect_32( x, y, width, height, dataPtr, alphaPtr, (unsigned int *) backBuffer, save, static_alpha ); + vc_blit_rect_32( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned int *) backBuffer, flags ); + break; + case 30: + vc_blit_rect_30( x, y, bx, width, height, sourceRow, backRow, dataPtr, (unsigned int *) backBuffer, flags ); break; } } -static void vc_blit_rect_8( int x, int y, - int width, int height, - const unsigned char * dataPtr, - const unsigned char * alphaPtr, - unsigned char * backPtr, - boolean_t save, boolean_t static_alpha ) +static void +vc_blit_rect_8(int x, int y, __unused int bx, + int width, int height, + int sourceRow, __unused int backRow, + const unsigned char * dataPtr, + __unused unsigned char * backBuffer, + __unused unsigned int flags) { - volatile unsigned char * dst; + volatile unsigned short * dst; int line, col; - unsigned int data; - - dst = (unsigned char *)(vinfo.v_baseaddr + - (y * vinfo.v_rowbytes) + - (x)); - - for( line = 0; line < height; line++) { - for( col = 0; col < width; col++) { - data = 0; - if( dataPtr != 0) data = *dataPtr++; - else if( alphaPtr != 0) data = vc_revclut8[*alphaPtr++]; - *(dst + col) = data; - } - dst = (volatile unsigned char *) (((int)dst) + vinfo.v_rowbytes); + unsigned int data = 0, out = 0; + int sx, sy, a, b, c, d; + int scale = 0x10000; + + a = vc_rotate_matr[kDataRotate & flags][0][0] * scale; + b = vc_rotate_matr[kDataRotate & flags][0][1] * scale; + c = vc_rotate_matr[kDataRotate & flags][1][0] * scale; + d = vc_rotate_matr[kDataRotate & flags][1][1] * scale; + sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0; + sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0; + + if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr; + else if (1 == sourceRow) a = 0; + + dst = (volatile unsigned short *) (vinfo.v_baseaddr + + (y * vinfo.v_rowbytes) + + (x * 4)); + + for( line = 0; line < height; line++) + { + for( col = 0; col < width; col++) + { + if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16) + + sourceRow * (((sy + (col * c) + (line * d)) >> 16))]; + if (kDataAlpha & flags) + out = vc_revclut8[data]; + else + out = data; + *(dst + col) = out; + } + dst = (volatile unsigned short *) (((volatile char*)dst) + vinfo.v_rowbytes); } } -static void vc_blit_rect_16( int x, int y, - int width, int height, - const unsigned char * dataPtr, - const unsigned char * alphaPtr, - unsigned short * backPtr, - boolean_t save, boolean_t static_alpha ) +/* For ARM, 16-bit is 565 (RGB); it is 1555 (XRGB) on other platforms */ + +#define CLUT_MASK_R 0xf8 +#define CLUT_MASK_G 0xf8 +#define CLUT_MASK_B 0xf8 +#define CLUT_SHIFT_R << 7 +#define CLUT_SHIFT_G << 2 +#define CLUT_SHIFT_B >> 3 +#define MASK_R 0x7c00 +#define MASK_G 0x03e0 +#define MASK_B 0x001f +#define MASK_R_8 0x3fc00 +#define MASK_G_8 0x01fe0 +#define MASK_B_8 0x000ff + +static void vc_blit_rect_16( int x, int y, int bx, + int width, int height, + int sourceRow, int backRow, + const unsigned char * dataPtr, + unsigned short * backPtr, + unsigned int flags) { volatile unsigned short * dst; int line, col; - unsigned int data, index, alpha, back; - - dst = (volatile unsigned short *)(vinfo.v_baseaddr + + unsigned int data = 0, out = 0, back = 0; + int sx, sy, a, b, c, d; + int scale = 0x10000; + + a = vc_rotate_matr[kDataRotate & flags][0][0] * scale; + b = vc_rotate_matr[kDataRotate & flags][0][1] * scale; + c = vc_rotate_matr[kDataRotate & flags][1][0] * scale; + d = vc_rotate_matr[kDataRotate & flags][1][1] * scale; + sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0; + sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0; + + if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr; + else if (1 == sourceRow) a = 0; + + if (backPtr) + backPtr += bx; + dst = (volatile unsigned short *) (vinfo.v_baseaddr + (y * vinfo.v_rowbytes) + (x * 2)); - for( line = 0; line < height; line++) { - for( col = 0; col < width; col++) { - if( dataPtr != 0) { - index = *dataPtr++; - index *= 3; + for( line = 0; line < height; line++) + { + for( col = 0; col < width; col++) + { + if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16) + + sourceRow * (((sy + (col * c) + (line * d)) >> 16))]; + if (backPtr) { + if (kSave & flags) { + back = *(dst + col); + *backPtr++ = back; + } else + back = *backPtr++; } + if (kDataIndexed & flags) { + out = ( (CLUT_MASK_R & (vc_clut[data*3 + 0])) CLUT_SHIFT_R) + | ( (CLUT_MASK_G & (vc_clut[data*3 + 1])) CLUT_SHIFT_G) + | ( (CLUT_MASK_B & (vc_clut[data*3 + 2])) CLUT_SHIFT_B); + } else if (kDataAlpha & flags) { + out = (((((back & MASK_R) * data) + MASK_R_8) >> 8) & MASK_R) + | (((((back & MASK_G) * data) + MASK_G_8) >> 8) & MASK_G) + | (((((back & MASK_B) * data) + MASK_B_8) >> 8) & MASK_B); +#ifdef CONFIG_VC_PROGRESS_WHITE + out += (((0xff - data) & CLUT_MASK_R) CLUT_SHIFT_R) + | (((0xff - data) & CLUT_MASK_G) CLUT_SHIFT_G) + | (((0xff - data) & CLUT_MASK_B) CLUT_SHIFT_B); +#endif + } else + out = back; + *(dst + col) = out; + } + dst = (volatile unsigned short *) (((volatile char*)dst) + vinfo.v_rowbytes); + if (backPtr) + backPtr += backRow - width; + } +} - if( alphaPtr && backPtr) { - - alpha = *alphaPtr++; - data = 0; - if( dataPtr != 0) { - if( vc_clut[index + 0] > alpha) - data |= (((vc_clut[index + 0] - alpha) & 0xf8) << 7); - if( vc_clut[index + 1] > alpha) - data |= (((vc_clut[index + 1] - alpha) & 0xf8) << 2); - if( vc_clut[index + 2] > alpha) - data |= (((vc_clut[index + 2] - alpha) & 0xf8) >> 3); - } - if( save) { - back = *(dst + col); - if ( !static_alpha) - *backPtr++ = back; - back = (((((back & 0x7c00) * alpha) + 0x3fc00) >> 8) & 0x7c00) - | (((((back & 0x03e0) * alpha) + 0x01fe0) >> 8) & 0x03e0) - | (((((back & 0x001f) * alpha) + 0x000ff) >> 8) & 0x001f); - if ( static_alpha) - *backPtr++ = back; - } else { - back = *backPtr++; - if ( !static_alpha) { - back = (((((back & 0x7c00) * alpha) + 0x3fc00) >> 8) & 0x7c00) - | (((((back & 0x03e0) * alpha) + 0x01fe0) >> 8) & 0x03e0) - | (((((back & 0x001f) * alpha) + 0x000ff) >> 8) & 0x001f); - } - } - - data += back; +static void vc_blit_rect_32(int x, int y, int bx, + int width, int height, + int sourceRow, int backRow, + const unsigned char * dataPtr, + unsigned int * backPtr, + unsigned int flags) +{ + volatile unsigned int * dst; + int line, col; + unsigned int data = 0, out = 0, back = 0; + int sx, sy, a, b, c, d; + int scale = 0x10000; + + a = vc_rotate_matr[kDataRotate & flags][0][0] * scale; + b = vc_rotate_matr[kDataRotate & flags][0][1] * scale; + c = vc_rotate_matr[kDataRotate & flags][1][0] * scale; + d = vc_rotate_matr[kDataRotate & flags][1][1] * scale; + sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0; + sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0; + + if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr; + else if (1 == sourceRow) a = 0; + + if (backPtr) + backPtr += bx; + dst = (volatile unsigned int *) (vinfo.v_baseaddr + + (y * vinfo.v_rowbytes) + + (x * 4)); + for( line = 0; line < height; line++) + { + for( col = 0; col < width; col++) + { + if (sourceRow) data = dataPtr[((sx + (col * a) + (line * b)) >> 16) + + sourceRow * (((sy + (col * c) + (line * d)) >> 16))]; + if (backPtr) { + if (kSave & flags) { + back = *(dst + col); + *backPtr++ = back; + } else + back = *backPtr++; + } + if (kDataIndexed & flags) { + out = (vc_clut[data*3 + 0] << 16) + | (vc_clut[data*3 + 1] << 8) + | (vc_clut[data*3 + 2]); + } else if (kDataAlpha & flags) { + out = (((((back & 0x00ff00ff) * data) + 0x00ff00ff) >> 8) & 0x00ff00ff) + | (((((back & 0x0000ff00) * data) + 0x0000ff00) >> 8) & 0x0000ff00); +#ifdef CONFIG_VC_PROGRESS_WHITE + out += ((0xff - data) << 16) + | ((0xff - data) << 8) + | (0xff - data); +#endif } else - if( dataPtr != 0) { - data = ( (0xf8 & (vc_clut[index + 0])) << 7) - | ( (0xf8 & (vc_clut[index + 1])) << 2) - | ( (0xf8 & (vc_clut[index + 2])) >> 3); - } - - *(dst + col) = data; + out = back; + *(dst + col) = out; } - dst = (volatile unsigned short *) (((int)dst) + vinfo.v_rowbytes); + dst = (volatile unsigned int *) (((volatile char*)dst) + vinfo.v_rowbytes); + if (backPtr) + backPtr += backRow - width; } } -static void vc_blit_rect_32( int x, int y, - int width, int height, - const unsigned char * dataPtr, - const unsigned char * alphaPtr, - unsigned int * backPtr, - boolean_t save, boolean_t static_alpha ) +static void vc_blit_rect_30(int x, int y, int bx, + int width, int height, + int sourceRow, int backRow, + const unsigned char * dataPtr, + unsigned int * backPtr, + unsigned int flags) { volatile unsigned int * dst; int line, col; - unsigned int data, index, alpha, back; - + unsigned int data = 0, out = 0, back = 0; + unsigned long long exp; + int sx, sy, a, b, c, d; + int scale = 0x10000; + + a = vc_rotate_matr[kDataRotate & flags][0][0] * scale; + b = vc_rotate_matr[kDataRotate & flags][0][1] * scale; + c = vc_rotate_matr[kDataRotate & flags][1][0] * scale; + d = vc_rotate_matr[kDataRotate & flags][1][1] * scale; + sx = ((a + b) < 0) ? ((width * scale) - 0x8000) : 0; + sy = ((c + d) < 0) ? ((height * scale) - 0x8000) : 0; + + if (!sourceRow) data = (unsigned int)(uintptr_t)dataPtr; + else if (1 == sourceRow) a = 0; + + if (backPtr) + backPtr += bx; dst = (volatile unsigned int *) (vinfo.v_baseaddr + (y * vinfo.v_rowbytes) + (x * 4)); - for( line = 0; line < height; line++) { - for( col = 0; col < width; col++) { - if( dataPtr != 0) { - index = *dataPtr++; - index *= 3; + for( line = 0; line < height; line++) + { + for( col = 0; col < width; col++) + { + if (col < sourceRow) + data = *dataPtr++; + + if (backPtr) { + if (kSave & flags) { + back = *(dst + col); + *backPtr++ = back; + } else + back = *backPtr++; } + if (kDataIndexed & flags) { + out = (vc_clut[data*3 + 0] << 22) + | (vc_clut[data*3 + 1] << 12) + | (vc_clut[data*3 + 2] << 2); + } else if (kDataAlpha & flags) { + exp = back; + exp = (((((exp & 0x3FF003FF) * data) + 0x0FF000FF) >> 8) & 0x3FF003FF) + | (((((exp & 0x000FFC00) * data) + 0x0003FC00) >> 8) & 0x000FFC00); + out = (unsigned int)exp; +#ifdef CONFIG_VC_PROGRESS_WHITE + out += ((0xFF - data) << 22) + | ((0xFF - data) << 12) + | ((0xFF - data) << 2); +#endif + } else + out = back; + *(dst + col) = out; + } + dst = (volatile unsigned int *) (((volatile char*)dst) + vinfo.v_rowbytes); + if (backPtr) + backPtr += backRow - width; + } +} - if( alphaPtr && backPtr) { - - alpha = *alphaPtr++; - data = 0; - if( dataPtr != 0) { - if( vc_clut[index + 0] > alpha) - data |= ((vc_clut[index + 0] - alpha) << 16); - if( vc_clut[index + 1] > alpha) - data |= ((vc_clut[index + 1] - alpha) << 8); - if( vc_clut[index + 2] > alpha) - data |= ((vc_clut[index + 2] - alpha)); - } - if( save) { - back = *(dst + col); - if ( !static_alpha) - *backPtr++ = back; - back = (((((back & 0x00ff00ff) * alpha) + 0x00ff00ff) >> 8) & 0x00ff00ff) - | (((((back & 0x0000ff00) * alpha) + 0x0000ff00) >> 8) & 0x0000ff00); - if ( static_alpha) - *backPtr++ = back; - } else { - back = *backPtr++; - if ( !static_alpha) { - back = (((((back & 0x00ff00ff) * alpha) + 0x00ff00ff) >> 8) & 0x00ff00ff) - | (((((back & 0x0000ff00) * alpha) + 0x0000ff00) >> 8) & 0x0000ff00); - } - } +/* + * Routines to render the lzss image format + */ - data += back; +struct lzss_image_state { + uint32_t col; + uint32_t row; + uint32_t width; + uint32_t height; + uint32_t bytes_per_row; + volatile uint32_t * row_start; + const uint8_t* clut; +}; +typedef struct lzss_image_state lzss_image_state; - } else - if( dataPtr != 0) { - data = (vc_clut[index + 0] << 16) - | (vc_clut[index + 1] << 8) - | (vc_clut[index + 2]); - } +// returns 0 if OK, 1 if error +static inline int +vc_decompress_lzss_next_pixel (int next_data, lzss_image_state* state) +{ + uint32_t palette_index = 0; + uint32_t pixel_value = 0; - *(dst + col) = data; - } - dst = (volatile unsigned int *) (((int)dst) + vinfo.v_rowbytes); + palette_index = next_data * 3; + + pixel_value = ( (uint32_t) state->clut[palette_index + 0] << 16) + | ( (uint32_t) state->clut[palette_index + 1] << 8) + | ( (uint32_t) state->clut[palette_index + 2]); + + *(state->row_start + state->col) = pixel_value; + + if (++state->col >= state->width) { + state->col = 0; + if (++state->row >= state->height) { + return 1; + } + state->row_start = (volatile uint32_t *) (((uintptr_t)state->row_start) + state->bytes_per_row); + } + return 0; +} + + +/* + * Blit an lzss compressed image to the framebuffer + * Assumes 32 bit screen (which is everything we ship at the moment) + * The function vc_display_lzss_icon was copied from libkern/mkext.c, then modified. + */ + +/* + * TODO: Does lzss use too much stack? 4096 plus bytes... + * Can probably chop it down by 1/2. + */ + +/************************************************************** + LZSS.C -- A Data Compression Program +*************************************************************** + 4/6/1989 Haruhiko Okumura + Use, distribute, and modify this program freely. + Please send me your improved versions. + PC-VAN SCIENCE + NIFTY-Serve PAF01022 + CompuServe 74050,1022 + +**************************************************************/ + +#define N 4096 /* size of ring buffer - must be power of 2 */ +#define F 18 /* upper limit for match_length */ +#define THRESHOLD 2 /* encode string into position and length + if match_length is greater than this */ + +// returns 0 if OK, 1 if error +// x and y indicate upper left corner of image location on screen +int +vc_display_lzss_icon(uint32_t dst_x, uint32_t dst_y, + uint32_t image_width, uint32_t image_height, + const uint8_t *compressed_image, + uint32_t compressed_size, + const uint8_t *clut) +{ + uint32_t* image_start; + uint32_t bytes_per_pixel = 4; + uint32_t bytes_per_row = vinfo.v_rowbytes; + + image_start = (uint32_t *) (vinfo.v_baseaddr + (dst_y * bytes_per_row) + (dst_x * bytes_per_pixel)); + + lzss_image_state state = {0, 0, image_width, image_height, bytes_per_row, image_start, clut}; + + int rval = 0; + + const uint8_t *src = compressed_image; + uint32_t srclen = compressed_size; + + /* ring buffer of size N, with extra F-1 bytes to aid string comparison */ + uint8_t text_buf[N + F - 1]; + const uint8_t *srcend = src + srclen; + int i, j, k, r, c; + unsigned int flags; + + srcend = src + srclen; + for (i = 0; i < N - F; i++) + text_buf[i] = ' '; + r = N - F; + flags = 0; + for ( ; ; ) { + if (((flags >>= 1) & 0x100) == 0) { + if (src < srcend) c = *src++; else break; + flags = c | 0xFF00; /* uses higher byte cleverly */ + } /* to count eight */ + if (flags & 1) { + if (src < srcend) c = *src++; else break; + rval = vc_decompress_lzss_next_pixel(c, &state); + if (rval != 0) + return rval; + text_buf[r++] = c; + r &= (N - 1); + } else { + if (src < srcend) i = *src++; else break; + if (src < srcend) j = *src++; else break; + i |= ((j & 0xF0) << 4); + j = (j & 0x0F) + THRESHOLD; + for (k = 0; k <= j; k++) { + c = text_buf[(i + k) & (N - 1)]; + rval = vc_decompress_lzss_next_pixel(c, &state); + if (rval != 0 ) + return rval; + text_buf[r++] = c; + r &= (N - 1); + } + } } + return 0; +} + +void noroot_icon_test(void) { + boolean_t o_vc_progress_enable = vc_progress_enable; + + vc_progress_enable = 1; + + PE_display_icon( 0, "noroot"); + + vc_progress_enable = o_vc_progress_enable; } + void vc_display_icon( vc_progress_element * desc, const unsigned char * data ) { @@ -1937,26 +2321,30 @@ void vc_display_icon( vc_progress_element * desc, x += ((vinfo.v_width - width) / 2); y += ((vinfo.v_height - height) / 2); } - vc_blit_rect( x, y, width, height, data, NULL, NULL, FALSE, TRUE ); + vc_blit_rect( x, y, 0, width, height, width, 0, data, NULL, kDataIndexed ); } } void vc_progress_initialize( vc_progress_element * desc, - const unsigned char * data, + const unsigned char * data1x, + const unsigned char * data2x, const unsigned char * clut ) { uint64_t abstime; - if( (!clut) || (!desc) || (!data)) + if( (!clut) || (!desc) || (!data1x)) return; vc_clut = clut; vc_clut8 = clut; + simple_lock_init(&vc_progress_lock, 0); + vc_progress = desc; - vc_progress_data = data; + vc_progress_data[0] = data1x; + vc_progress_data[1] = data2x; if( 2 & vc_progress->flags) - vc_progress_alpha = vc_progress_data + vc_progress_alpha = data1x + vc_progress->count * vc_progress->width * vc_progress->height; else vc_progress_alpha = NULL; @@ -1964,16 +2352,14 @@ vc_progress_initialize( vc_progress_element * desc, thread_call_setup(&vc_progress_call, vc_progress_task, NULL); clock_interval_to_absolutetime_interval(vc_progress->time, 1000 * 1000, &abstime); - vc_progress_interval = abstime; - - simple_lock_init(&vc_progress_lock, 0); + vc_progress_interval = (uint32_t)abstime; } -static void -vc_progress_set( boolean_t enable, uint32_t delay ) +void +vc_progress_set(boolean_t enable, uint32_t vc_delay) { spl_t s; - void *saveBuf = 0; + void *saveBuf = NULL; vm_size_t saveLen = 0; unsigned int count; unsigned int index; @@ -1987,7 +2373,7 @@ vc_progress_set( boolean_t enable, uint32_t delay ) return; if( enable) { - saveLen = vc_progress->width * vc_progress->height * vinfo.v_depth / 8; + saveLen = (vc_progress->width << vc_uiselect) * (vc_progress->height << vc_uiselect) * vinfo.v_depth / 8; saveBuf = kalloc( saveLen ); switch( vinfo.v_depth) { @@ -2009,9 +2395,9 @@ vc_progress_set( boolean_t enable, uint32_t delay ) case 16 : buf16 = (unsigned short *) saveBuf; - pdata16 = ((vc_clut[0x01 * 3 + 0] & 0xf8) << 7) - | ((vc_clut[0x01 * 3 + 0] & 0xf8) << 2) - | ((vc_clut[0x01 * 3 + 0] & 0xf8) >> 3); + pdata16 = ((vc_clut[0x01 * 3 + 0] & CLUT_MASK_R) CLUT_SHIFT_R) + | ((vc_clut[0x01 * 3 + 0] & CLUT_MASK_G) CLUT_SHIFT_G) + | ((vc_clut[0x01 * 3 + 0] & CLUT_MASK_B) CLUT_SHIFT_B); for( count = 0; count < saveLen / 2; count++) buf16[count] = pdata16; break; @@ -2036,17 +2422,21 @@ vc_progress_set( boolean_t enable, uint32_t delay ) vc_needsave = TRUE; vc_saveunder = saveBuf; vc_saveunder_len = saveLen; - saveBuf = 0; - saveLen = 0; - - clock_interval_to_deadline(delay, 1000 * 1000 * 1000 /*second scale*/, &vc_progress_deadline); + saveBuf = NULL; + saveLen = 0; + vc_progress_count = 0; + vc_progress_angle = 0; + + clock_interval_to_deadline(vc_delay, + 1000 * 1000 * 1000 /*second scale*/, + &vc_progress_deadline); thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline); } else { if( vc_saveunder) { saveBuf = vc_saveunder; saveLen = vc_saveunder_len; - vc_saveunder = 0; + vc_saveunder = NULL; vc_saveunder_len = 0; } @@ -2061,10 +2451,11 @@ vc_progress_set( boolean_t enable, uint32_t delay ) kfree( saveBuf, saveLen ); } -static void vc_progress_task( void * arg0, void * arg ) + +static void +vc_progress_task(__unused void *arg0, __unused void *arg) { spl_t s; - int count = (int) arg; int x, y, width, height; const unsigned char * data; @@ -2073,27 +2464,32 @@ static void vc_progress_task( void * arg0, void * arg ) if( vc_progress_enable) { - count++; - if( count >= vc_progress->count) - count = 0; + vc_progress_count++; + if( vc_progress_count >= vc_progress->count) { + vc_progress_count = 0; + vc_progress_angle++; + } - width = vc_progress->width; - height = vc_progress->height; - x = vc_progress->dx; - y = vc_progress->dy; - data = vc_progress_data; - data += count * width * height; + width = (vc_progress->width << vc_uiselect); + height = (vc_progress->height << vc_uiselect); + x = (vc_progress->dx << vc_uiselect); + y = (vc_progress->dy << vc_uiselect); + data = vc_progress_data[vc_uiselect]; + data += vc_progress_count * width * height; if( 1 & vc_progress->flags) { x += ((vinfo.v_width - width) / 2); y += ((vinfo.v_height - height) / 2); } - vc_blit_rect( x, y, width, height, - NULL, data, vc_saveunder, - vc_needsave, (0 == (4 & vc_progress->flags)) ); + vc_blit_rect( x, y, 0, + width, height, width, width, + data, vc_saveunder, + kDataAlpha + | (vc_progress_angle & kDataRotate) + | (vc_needsave ? kSave : 0) ); vc_needsave = FALSE; clock_deadline_for_periodic_event(vc_progress_interval, mach_absolute_time(), &vc_progress_deadline); - thread_call_enter1_delayed(&vc_progress_call, (void *)count, vc_progress_deadline); + thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline); } simple_unlock(&vc_progress_lock); splx(s); @@ -2104,46 +2500,100 @@ static void vc_progress_task( void * arg0, void * arg ) * ------------------------------------------- */ -#ifdef __i386__ -#include -#endif /* __i386__ */ +#if defined (__i386__) || defined (__x86_64__) +#include +#endif static boolean_t gc_acquired = FALSE; static boolean_t gc_graphics_boot = FALSE; +static boolean_t gc_desire_text = FALSE; + +static uint64_t lastVideoPhys = 0; +static vm_offset_t lastVideoVirt = 0; +static vm_size_t lastVideoSize = 0; +static boolean_t lastVideoMapped = FALSE; + +static void +gc_pause( boolean_t pause, boolean_t graphics_now ) +{ + spl_t s; + + s = splhigh( ); + VCPUTC_LOCK_LOCK( ); + + disableConsoleOutput = (pause && !console_is_serial()); + gc_enabled = (!pause && !graphics_now); + + VCPUTC_LOCK_UNLOCK( ); + + simple_lock(&vc_progress_lock); + + vc_progress_enable = gc_graphics_boot && !gc_desire_text && !pause; + if (vc_progress_enable) + thread_call_enter_delayed(&vc_progress_call, vc_progress_deadline); + + simple_unlock(&vc_progress_lock); + splx(s); +} + +static void +vc_initialize(__unused struct vc_info * vinfo_p) +{ -static unsigned int lastVideoPhys = 0; -static unsigned int lastVideoVirt = 0; -static unsigned int lastVideoSize = 0; + vinfo.v_rows = vinfo.v_height / ISO_CHAR_HEIGHT; + vinfo.v_columns = vinfo.v_width / ISO_CHAR_WIDTH; + vinfo.v_rowscanbytes = ((vinfo.v_depth + 7) / 8) * vinfo.v_width; + vc_uiselect = (2 == vinfo.v_scale) ? 1 : 0; +} void -initialize_screen(Boot_Video * boot_vinfo, unsigned int op) +initialize_screen(PE_Video * boot_vinfo, unsigned int op) { - unsigned int fbsize; - unsigned int newVideoVirt; + unsigned int fbsize = 0; + vm_offset_t newVideoVirt = 0; + boolean_t graphics_now; ppnum_t fbppage; if ( boot_vinfo ) { -// bcopy((const void *)boot_vinfo, (void *)&boot_video_info, sizeof(boot_video_info)); - + struct vc_info new_vinfo = vinfo; /* * First, check if we are changing the size and/or location of the framebuffer */ + new_vinfo.v_name[0] = 0; + new_vinfo.v_physaddr = boot_vinfo->v_baseAddr & ~3; /* Get the physical address */ +#ifndef __LP64__ + new_vinfo.v_physaddr |= (((uint64_t) boot_vinfo->v_baseAddrHigh) << 32); +#endif + if (kPEBaseAddressChange != op) + { + new_vinfo.v_width = (unsigned int)boot_vinfo->v_width; + new_vinfo.v_height = (unsigned int)boot_vinfo->v_height; + new_vinfo.v_depth = (unsigned int)boot_vinfo->v_depth; + new_vinfo.v_rowbytes = (unsigned int)boot_vinfo->v_rowBytes; +#if defined(__i386__) || defined(__x86_64__) + new_vinfo.v_type = (unsigned int)boot_vinfo->v_display; +#else + new_vinfo.v_type = 0; +#endif + unsigned int scale = (unsigned int)boot_vinfo->v_scale; + if (scale == kPEScaleFactor1x ) + new_vinfo.v_scale = kPEScaleFactor1x; + else if (scale == kPEScaleFactor2x) + new_vinfo.v_scale = kPEScaleFactor2x; + else /* Scale factor not set, default to 1x */ + new_vinfo.v_scale = kPEScaleFactor1x; - vinfo.v_name[0] = 0; - vinfo.v_width = boot_vinfo->v_width; - vinfo.v_height = boot_vinfo->v_height; - vinfo.v_depth = boot_vinfo->v_depth; - vinfo.v_rowbytes = boot_vinfo->v_rowBytes; - vinfo.v_physaddr = boot_vinfo->v_baseAddr; /* Get the physical address */ - - kprintf("initialize_screen: b=%08X, w=%08X, h=%08X, r=%08X\n", /* (BRINGUP) */ - vinfo.v_physaddr, vinfo.v_width, vinfo.v_height, vinfo.v_rowbytes); /* (BRINGUP) */ + } + + if (!lastVideoMapped) + kprintf("initialize_screen: b=%08llX, w=%08X, h=%08X, r=%08X, d=%08X\n", /* (BRINGUP) */ + new_vinfo.v_physaddr, new_vinfo.v_width, new_vinfo.v_height, new_vinfo.v_rowbytes, new_vinfo.v_type); /* (BRINGUP) */ - if (!vinfo.v_physaddr) /* Check to see if we have a framebuffer */ + if (!new_vinfo.v_physaddr) /* Check to see if we have a framebuffer */ { kprintf("initialize_screen: No video - forcing serial mode\n"); /* (BRINGUP) */ - vinfo.v_depth = 0; /* vc routines are nop */ + new_vinfo.v_depth = 0; /* vc routines are nop */ (void)switch_to_serial_console(); /* Switch into serial mode */ gc_graphics_boot = FALSE; /* Say we are not in graphics mode */ disableConsoleOutput = FALSE; /* Allow printfs to happen */ @@ -2152,68 +2602,78 @@ initialize_screen(Boot_Video * boot_vinfo, unsigned int op) else { /* - * Note that for the first time only, boot_vinfo->v_baseAddr is physical. - */ - - if (kernel_map != VM_MAP_NULL) /* If VM is up, we are given a virtual address */ + * If VM is up, we are given a virtual address, unless b0 is set to indicate physical. + */ + if ((kernel_map != VM_MAP_NULL) && (0 == (1 & boot_vinfo->v_baseAddr))) { fbppage = pmap_find_phys(kernel_pmap, (addr64_t)boot_vinfo->v_baseAddr); /* Get the physical address of frame buffer */ if(!fbppage) /* Did we find it? */ { - panic("initialize_screen: Strange framebuffer - addr = %08X\n", boot_vinfo->v_baseAddr); + panic("initialize_screen: Strange framebuffer - addr = %08X\n", (uint32_t)boot_vinfo->v_baseAddr); } - vinfo.v_physaddr = (fbppage << 12) | (boot_vinfo->v_baseAddr & PAGE_MASK); /* Get the physical address */ + new_vinfo.v_physaddr = (((uint64_t)fbppage) << 12) | (boot_vinfo->v_baseAddr & PAGE_MASK); /* Get the physical address */ } -#ifdef __i386__ - vinfo.v_type = boot_vinfo->v_display; -#else - vinfo.v_type = 0; -#endif - - fbsize = round_page_32(vinfo.v_height * vinfo.v_rowbytes); /* Remember size */ - - if ((lastVideoPhys != vinfo.v_physaddr) || (fbsize > lastVideoSize)) /* Did framebuffer change location or get bigger? */ - { - newVideoVirt = io_map_spec((vm_offset_t)vinfo.v_physaddr, fbsize); /* Allocate address space for framebuffer */ - - if (lastVideoVirt) /* Was the framebuffer mapped before? */ - { - pmap_remove(kernel_pmap, trunc_page_64(lastVideoVirt), - round_page_64(lastVideoVirt + lastVideoSize)); /* Toss mappings */ + if (boot_vinfo->v_length != 0) + fbsize = (unsigned int) round_page(boot_vinfo->v_length); + else + fbsize = (unsigned int) round_page(new_vinfo.v_height * new_vinfo.v_rowbytes); /* Remember size */ - if(lastVideoVirt <= vm_last_addr) /* Was this not a special pre-VM mapping? */ - { - kmem_free(kernel_map, lastVideoVirt, lastVideoSize); /* Toss kernel addresses */ - } - } - lastVideoPhys = vinfo.v_physaddr; /* Remember the framebuffer address */ - lastVideoSize = fbsize; /* Remember the size */ - lastVideoVirt = newVideoVirt; /* Remember the virtual framebuffer address */ - } + if ((lastVideoPhys != new_vinfo.v_physaddr) || (fbsize > lastVideoSize)) /* Did framebuffer change location or get bigger? */ + { + unsigned int flags = VM_WIMG_IO; + newVideoVirt = io_map_spec((vm_map_offset_t)new_vinfo.v_physaddr, fbsize, flags); /* Allocate address space for framebuffer */ + } } - vinfo.v_baseaddr = lastVideoVirt; /* Set the new framebuffer address */ + if (newVideoVirt != 0) + new_vinfo.v_baseaddr = newVideoVirt + boot_vinfo->v_offset; /* Set the new framebuffer address */ + else + new_vinfo.v_baseaddr = lastVideoVirt + boot_vinfo->v_offset; /* Set the new framebuffer address */ + +#if defined(__x86_64__) + // Adjust the video buffer pointer to point to where it is in high virtual (above the hole) + new_vinfo.v_baseaddr |= (VM_MIN_KERNEL_ADDRESS & ~LOW_4GB_MASK); +#endif -#ifdef __i386__ - if ( (vinfo.v_type == TEXT_MODE) ) + /* Update the vinfo structure atomically with respect to the vc_progress task if running */ + if (vc_progress) { - // Text mode setup by the booter. - - gc_ops.initialize = tc_initialize; - gc_ops.enable = tc_enable; - gc_ops.paint_char = tc_paint_char; - gc_ops.clear_screen = tc_clear_screen; - gc_ops.scroll_down = tc_scroll_down; - gc_ops.scroll_up = tc_scroll_up; - gc_ops.hide_cursor = tc_hide_cursor; - gc_ops.show_cursor = tc_show_cursor; - gc_ops.update_color = tc_update_color; + simple_lock(&vc_progress_lock); + vinfo = new_vinfo; + simple_unlock(&vc_progress_lock); } else -#endif /* __i386__ */ { + vinfo = new_vinfo; + } + + // If we changed the virtual address, remove the old mapping + if (newVideoVirt != 0) + { + if (lastVideoVirt) /* Was the framebuffer mapped before? */ + { +#if FALSE + if(lastVideoMapped) /* Was this not a special pre-VM mapping? */ +#endif + { + pmap_remove(kernel_pmap, trunc_page_64(lastVideoVirt), + round_page_64(lastVideoVirt + lastVideoSize)); /* Toss mappings */ + } + if(lastVideoMapped) /* Was this not a special pre-VM mapping? */ + { + kmem_free(kernel_map, lastVideoVirt, lastVideoSize); /* Toss kernel addresses */ + } + } + lastVideoPhys = new_vinfo.v_physaddr; /* Remember the framebuffer address */ + lastVideoSize = fbsize; /* Remember the size */ + lastVideoVirt = newVideoVirt; /* Remember the virtual framebuffer address */ + lastVideoMapped = (NULL != kernel_map); + } + + if (kPEBaseAddressChange != op) + { // Graphics mode setup by the booter. gc_ops.initialize = vc_initialize; @@ -2225,56 +2685,77 @@ initialize_screen(Boot_Video * boot_vinfo, unsigned int op) gc_ops.hide_cursor = vc_reverse_cursor; gc_ops.show_cursor = vc_reverse_cursor; gc_ops.update_color = vc_update_color; + gc_initialize(&vinfo); } - gc_initialize(&vinfo); - #ifdef GRATEFULDEBUGGER GratefulDebInit((bootBumbleC *)boot_vinfo); /* Re-initialize GratefulDeb */ #endif /* GRATEFULDEBUGGER */ } + graphics_now = gc_graphics_boot && !gc_desire_text; switch ( op ) { case kPEGraphicsMode: - panicDialogDesired = TRUE; gc_graphics_boot = TRUE; + gc_desire_text = FALSE; break; case kPETextMode: - panicDialogDesired = FALSE; + disable_debug_output = FALSE; gc_graphics_boot = FALSE; break; case kPEAcquireScreen: if ( gc_acquired ) break; - - vc_progress_set( gc_graphics_boot, kProgressAcquireDelay ); - gc_enable( !gc_graphics_boot ); + vc_progress_set( graphics_now, kProgressAcquireDelay ); + gc_enable( !graphics_now ); gc_acquired = TRUE; + gc_desire_text = FALSE; + break; + + case kPEDisableScreen: + if (gc_acquired) + { + gc_pause( TRUE, graphics_now ); + } break; case kPEEnableScreen: - /* deprecated */ + if (gc_acquired) + { + gc_pause( FALSE, graphics_now ); + } break; case kPETextScreen: - panicDialogDesired = FALSE; - if ( gc_acquired == FALSE ) break; + if ( console_is_serial() ) break; + + disable_debug_output = FALSE; + if ( gc_acquired == FALSE ) + { + gc_desire_text = TRUE; + break; + } if ( gc_graphics_boot == FALSE ) break; vc_progress_set( FALSE, 0 ); +#if !CONFIG_EMBEDDED + vc_enable_progressmeter( FALSE ); +#endif gc_enable( TRUE ); break; - case kPEDisableScreen: - /* deprecated */ - /* skip break */ - case kPEReleaseScreen: gc_acquired = FALSE; + gc_desire_text = FALSE; gc_enable( FALSE ); + if ( gc_graphics_boot == FALSE ) break; + vc_progress_set( FALSE, 0 ); +#if !CONFIG_EMBEDDED + vc_enable_progressmeter( FALSE ); +#endif vc_clut8 = NULL; #ifdef GRATEFULDEBUGGER @@ -2287,36 +2768,63 @@ initialize_screen(Boot_Video * boot_vinfo, unsigned int op) #endif /* GRATEFULDEBUGGER */ } -void -refresh_screen(void) +void +dim_screen(void) { - if ( gc_enabled ) - { - gc_refresh_screen(); - gc_show_cursor(gc_x, gc_y); + unsigned int *p, *endp, *row; + int col, rowline, rowlongs; + register unsigned int mask; + + if(!vinfo.v_depth) + return; + + if ( vinfo.v_depth == 32 ) + mask = 0x007F7F7F; + else if ( vinfo.v_depth == 30 ) + mask = (0x1ff<<20) | (0x1ff<<10) | 0x1ff; + else if ( vinfo.v_depth == 16 ) + mask = 0x3DEF3DEF; + else + return; + + rowline = (int)(vinfo.v_rowscanbytes / 4); + rowlongs = (int)(vinfo.v_rowbytes / 4); + + p = (unsigned int*) vinfo.v_baseaddr; + endp = p + (rowlongs * vinfo.v_height); + + for (row = p ; row < endp ; row += rowlongs) { + for (p = &row[0], col = 0; col < rowline; col++) { + *p = (*p >> 1) & mask; + ++p; + } } } +void vcattach(void); /* XXX gcc 4 warning cleanup */ + void vcattach(void) { - extern struct { long msg_magic; long msg_bufx; long msg_bufr; char msg_bufc[]; } * msgbufp; - vm_initialized = TRUE; if ( gc_graphics_boot == FALSE ) { - unsigned int index; + long index; if ( gc_acquired ) { - initialize_screen( 0, kPEReleaseScreen ); + initialize_screen(NULL, kPEReleaseScreen); } - initialize_screen( 0, kPEAcquireScreen ); + initialize_screen(NULL, kPEAcquireScreen); for ( index = 0 ; index < msgbufp->msg_bufx ; index++ ) { + if (msgbufp->msg_bufc[index] == '\0') { + continue; + } + vcputc( 0, 0, msgbufp->msg_bufc[index] ); if ( msgbufp->msg_bufc[index] == '\n' ) @@ -2326,3 +2834,146 @@ vcattach(void) } } } + +#if !CONFIG_EMBEDDED + +int vc_progress_meter_enable; +int vc_progress_meter_value; + +static void * vc_progress_meter_backbuffer; +static int vc_progress_meter_drawn; + +static void +vc_draw_progress_meter(int select, unsigned int flags, int x1, int x2) +{ + const unsigned char * data; + int x, w; + int ox, oy; + + ox = ((vinfo.v_width - (kProgressBarWidth << vc_uiselect)) / 2); + oy = vinfo.v_height - (((vinfo.v_height / 2) - ((vc_progress->dy + kProgressBarHeight) << vc_uiselect)) / 2); + + if (kDataBack == flags) + { + // restore back bits + vc_blit_rect(ox + x1, oy, x1, + x2, (kProgressBarHeight << vc_uiselect), 0, (kProgressBarWidth << vc_uiselect), + NULL, vc_progress_meter_backbuffer, flags); + return; + } + + for (x = x1; x < x2; x += w) + { + if (x < (kProgressBarCapWidth << vc_uiselect)) + { + if (x2 < (kProgressBarCapWidth << vc_uiselect)) + w = x2 - x; + else + w = (kProgressBarCapWidth << vc_uiselect) - x; + data = progressmeter_leftcap[vc_uiselect & 1][select & 1]; + data += x; + vc_blit_rect(ox + x, oy, x, w, + (kProgressBarHeight << vc_uiselect), + (kProgressBarCapWidth << vc_uiselect), + (kProgressBarWidth << vc_uiselect), + data, vc_progress_meter_backbuffer, flags); + } + else if (x < ((kProgressBarWidth - kProgressBarCapWidth) << vc_uiselect)) + { + if (x2 < ((kProgressBarWidth - kProgressBarCapWidth) << vc_uiselect)) + w = x2 - x; + else + w = ((kProgressBarWidth - kProgressBarCapWidth) << vc_uiselect) - x; + data = progressmeter_middle[vc_uiselect & 1][select & 1]; + vc_blit_rect(ox + x, oy, x, w, + (kProgressBarHeight << vc_uiselect), + 1, + (kProgressBarWidth << vc_uiselect), + data, vc_progress_meter_backbuffer, flags); + } + else + { + w = x2 - x; + data = progressmeter_rightcap[vc_uiselect & 1][select & 1]; + data += x - ((kProgressBarWidth - kProgressBarCapWidth) << vc_uiselect); + vc_blit_rect(ox + x, oy, x, w, + (kProgressBarHeight << vc_uiselect), + (kProgressBarCapWidth << vc_uiselect), + (kProgressBarWidth << vc_uiselect), + data, vc_progress_meter_backbuffer, flags); + } + } +} + +void +vc_enable_progressmeter(int new_value) +{ + spl_t s; + void * new_buffer = NULL; + + if (new_value) + new_buffer = kalloc((kProgressBarWidth << vc_uiselect) + * (kProgressBarHeight << vc_uiselect) * sizeof(int)); + + s = splhigh(); + simple_lock(&vc_progress_lock); + + if (gc_enabled || !gc_acquired || !gc_graphics_boot) + new_value = FALSE; + + if (new_value != vc_progress_meter_enable) + { + if (new_value) + { + vc_progress_meter_backbuffer = new_buffer; + vc_draw_progress_meter(FALSE, kDataAlpha | kSave, 0, (kProgressBarWidth << vc_uiselect)); + vc_progress_meter_enable = TRUE; + new_buffer = NULL; + vc_progress_meter_drawn = 0; + } + else if (vc_progress_meter_backbuffer) + { + vc_draw_progress_meter(0, kDataBack, 0, (kProgressBarWidth << vc_uiselect)); + new_buffer = vc_progress_meter_backbuffer; + vc_progress_meter_backbuffer = NULL; + vc_progress_meter_enable = FALSE; + } + } + + simple_unlock(&vc_progress_lock); + splx(s); + + if (new_buffer) + kfree(new_buffer, (kProgressBarWidth << vc_uiselect) + * (kProgressBarHeight << vc_uiselect) * sizeof(int)); +} + +void +vc_set_progressmeter(int new_value) +{ + spl_t s; + int x2; + + if ((new_value < 0) | (new_value > 100)) + return; + + s = splhigh(); + simple_lock(&vc_progress_lock); + + if (vc_progress_meter_enable) + { + vc_progress_meter_value = new_value; + x2 = ((kProgressBarWidth << vc_uiselect) * new_value) / 100; + if (x2 > vc_progress_meter_drawn) + vc_draw_progress_meter(TRUE, kDataAlpha, vc_progress_meter_drawn, x2); + else + vc_draw_progress_meter(FALSE, kDataAlpha, x2, vc_progress_meter_drawn); + vc_progress_meter_drawn = x2; + } + + simple_unlock(&vc_progress_lock); + splx(s); +} + +#endif /* !CONFIG_EMBEDDED */ +