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