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