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