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