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