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