]> git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/AT386/video_console.c
xnu-344.21.73.tar.gz
[apple/xnu.git] / osfmk / i386 / AT386 / 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 #include <kern/spl.h>
102 #include <machine/machparam.h> /* spl definitions */
103 #include "iso_scan_font.h"
104 #include <pexpert/pexpert.h>
105 #include <pexpert/i386/boot.h>
106 #include <kern/time_out.h>
107 #include <kern/lock.h>
108 #include "video_console.h"
109
110 #define CHARWIDTH 8
111 #define CHARHEIGHT 16
112
113 #define ATTR_NONE 0
114 #define ATTR_BOLD 1
115 #define ATTR_UNDER 2
116 #define ATTR_REVERSE 4
117
118 enum vt100state_e {
119 ESnormal, /* Nothing yet */
120 ESesc, /* Got ESC */
121 ESsquare, /* Got ESC [ */
122 ESgetpars, /* About to get or getting the parameters */
123 ESgotpars, /* Finished getting the parameters */
124 ESfunckey, /* Function key */
125 EShash, /* DEC-specific stuff (screen align, etc.) */
126 ESsetG0, /* Specify the G0 character set */
127 ESsetG1, /* Specify the G1 character set */
128 ESask,
129 EScharsize,
130 ESignore /* Ignore this sequence */
131 } vt100state = ESnormal;
132
133 static struct vc_info vinfo;
134 #define IS_TEXT_MODE (vinfo.v_type == TEXT_MODE)
135
136 /* Calculated in vccninit(): */
137 static int vc_wrap_mode = 1, vc_relative_origin = 0;
138 static int vc_charset_select = 0, vc_save_charset_s = 0;
139 static int vc_charset[2] = { 0, 0 };
140 static int vc_charset_save[2] = { 0, 0 };
141
142 /* VT100 state: */
143 #define MAXPARS 16
144 static int x = 0, y = 0, savex, savey;
145 static int par[MAXPARS], numpars, hanging_cursor, attr, saveattr;
146
147 /* VT100 tab stops & scroll region */
148 static char tab_stops[255];
149 static int scrreg_top, scrreg_bottom;
150
151 /* Misc */
152 void vc_flush_forward_buffer(void);
153 void vc_store_char(unsigned char);
154
155 /*
156 * For the color support (Michel Pollet)
157 */
158 unsigned char vc_color_index_table[33] =
159 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
160 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
161
162 unsigned long vc_color_depth_masks[4] =
163 { 0x000000FF, 0x00007FFF, 0x00FFFFFF };
164
165 unsigned long vc_colors[8][3] = {
166 { 0xFFFFFFFF, 0x00000000, 0x00000000 }, /* black */
167 { 0x23232323, 0x7C007C00, 0x00FF0000 }, /* red */
168 { 0xb9b9b9b9, 0x03e003e0, 0x0000FF00 }, /* green */
169 { 0x05050505, 0x7FE07FE0, 0x00FFFF00 }, /* yellow */
170 { 0xd2d2d2d2, 0x001f001f, 0x000000FF}, /* blue */
171 // { 0x80808080, 0x31933193, 0x00666699 }, /* blue */
172 { 0x18181818, 0x7C1F7C1F, 0x00FF00FF }, /* magenta */
173 { 0xb4b4b4b4, 0x03FF03FF, 0x0000FFFF }, /* cyan */
174 { 0x00000000, 0x7FFF7FFF, 0x00FFFFFF } /* white */
175 };
176
177 unsigned long vc_color_mask = 0;
178 unsigned long vc_color_fore = 0;
179 unsigned long vc_color_back = 0;
180 int vc_normal_background = 1;
181
182 /*
183 * For the jump scroll and buffering (Michel Pollet)
184 * 80*22 means on a 80*24 screen, the screen will
185 * scroll jump almost a full screen
186 * keeping only what's necessary for you to be able to read ;-)
187 */
188 #define VC_MAX_FORWARD_SIZE (80*22)
189
190 /*
191 * Delay between console updates in clock hz units, the larger the
192 * delay the fuller the jump-scroll buffer will be and so the faster the
193 * (scrolling) output. The smaller the delay, the less jerky the
194 * display. Heuristics show that at 10 touch-typists (Mike!) complain
195 */
196 #define VC_CONSOLE_UPDATE_TIMEOUT 5
197
198 static unsigned char vc_forward_buffer[VC_MAX_FORWARD_SIZE];
199 static long vc_forward_buffer_size = 0;
200 decl_simple_lock_data(,vc_forward_lock)
201
202 /* Set to 1 by initialize_screen() */
203 static int vc_initialized = 0;
204
205 /* Function pointers initialized via initialize_screen() */
206 static struct {
207 void (*initialize)(struct vc_info * vinfo_p);
208 void (*paintchar)(unsigned char c, int x, int y, int attrs);
209 void (*scrolldown)(int num);
210 void (*scrollup)(int num);
211 void (*clear_screen)(int xx, int yy, int which);
212 void (*show_cursor)(int x, int y);
213 void (*hide_cursor)(int x, int y);
214 void (*update_color)(int color, int fore);
215 } vc_ops;
216
217 /*
218 * New Rendering code from Michel Pollet
219 */
220
221 #define REN_MAX_DEPTH 32
222 /* that's the size for a 32 bits buffer... */
223 #define REN_MAX_SIZE (128L*1024)
224 unsigned char renderedFont[REN_MAX_SIZE];
225
226 /* Rendered Font Size */
227 unsigned long vc_rendered_font_size = REN_MAX_SIZE;
228 long vc_rendered_error = 0;
229
230 /* If the one bit table was reversed */
231 short vc_one_bit_reversed = 0;
232
233 /* Size of a character in the table (bytes) */
234 int vc_rendered_char_size = 0;
235
236 /*
237 # Attribute codes:
238 # 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
239 # Text color codes:
240 # 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
241 # Background color codes:
242 # 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
243 */
244
245 #define VC_RESET_BACKGROUND 40
246 #define VC_RESET_FOREGROUND 37
247
248 static void vc_color_set(int color)
249 {
250 if (vinfo.v_depth < 8)
251 return;
252 if (color >= 30 && color <= 37) {
253 vc_color_fore = vc_colors[color-30][vc_color_index_table[vinfo.v_depth]];
254 if ( vc_ops.update_color ) vc_ops.update_color(color - 30, 1);
255 }
256 if (color >= 40 && color <= 47) {
257 vc_color_back = vc_colors[color-40][vc_color_index_table[vinfo.v_depth]];
258 if ( vc_ops.update_color ) vc_ops.update_color(color - 40, 0);
259 vc_normal_background = color == 40;
260 }
261 }
262
263 static void vc_render_font(short olddepth, short newdepth)
264 {
265 int charIndex; /* index in ISO font */
266 union {
267 unsigned char *charptr;
268 unsigned short *shortptr;
269 unsigned long *longptr;
270 } current; /* current place in rendered font, multiple types. */
271
272 unsigned char *theChar; /* current char in iso_font */
273
274 if (olddepth == newdepth)
275 return; /* nothing to do */
276
277 vc_rendered_font_size = REN_MAX_SIZE;
278 if (newdepth == 1) {
279 vc_rendered_char_size = 16;
280 if (!vc_one_bit_reversed) { /* reverse the font for the blitter */
281 int i;
282 for (i = 0; i < ((ISO_CHAR_MAX-ISO_CHAR_MIN+1) * vc_rendered_char_size); i++) {
283 if (iso_font[i]) {
284 unsigned char mask1 = 0x80;
285 unsigned char mask2 = 0x01;
286 unsigned char val = 0;
287 while (mask1) {
288 if (iso_font[i] & mask1)
289 val |= mask2;
290 mask1 >>= 1;
291 mask2 <<= 1;
292 }
293 renderedFont[i] = ~val;
294 } else renderedFont[i] = 0xff;
295 }
296 vc_one_bit_reversed = 1;
297 }
298 return;
299 }
300 {
301 long csize = newdepth / 8; /* bytes per pixel */
302 vc_rendered_char_size = csize ? CHARHEIGHT * (csize * CHARWIDTH) :
303 /* for 2 & 4 */ CHARHEIGHT * (CHARWIDTH/(6-newdepth));
304 csize = (ISO_CHAR_MAX-ISO_CHAR_MIN+1) * vc_rendered_char_size;
305 if (csize > vc_rendered_font_size) {
306 vc_rendered_error = csize;
307 return;
308 } else
309 vc_rendered_font_size = csize;
310 }
311
312 current.charptr = renderedFont;
313 theChar = iso_font;
314 for (charIndex = ISO_CHAR_MIN; charIndex <= ISO_CHAR_MAX; charIndex++) {
315 int line;
316 for (line = 0; line < CHARHEIGHT; line++) {
317 unsigned char mask = 1;
318 do {
319 switch (newdepth) {
320 case 2: {
321 unsigned char value = 0;
322 if (*theChar & mask) value |= 0xC0; mask <<= 1;
323 if (*theChar & mask) value |= 0x30; mask <<= 1;
324 if (*theChar & mask) value |= 0x0C; mask <<= 1;
325 if (*theChar & mask) value |= 0x03;
326 value = ~value;
327 *current.charptr++ = value;
328 }
329 break;
330 case 4:
331 {
332 unsigned char value = 0;
333 if (*theChar & mask) value |= 0xF0; mask <<= 1;
334 if (*theChar & mask) value |= 0x0F;
335 value = ~value;
336 *current.charptr++ = value;
337 }
338 break;
339 case 8:
340 *current.charptr++ = (*theChar & mask) ? 0xff : 0;
341 break;
342 case 16:
343 *current.shortptr++ = (*theChar & mask) ? 0xFFFF : 0;
344 break;
345
346 case 32:
347 *current.longptr++ = (*theChar & mask) ? 0xFFFFFFFF : 0;
348 break;
349 }
350 mask <<= 1;
351 } while (mask); /* while the single bit drops to the right */
352 theChar++;
353 }
354 }
355 }
356
357 static void vc_paint_char1(unsigned char ch, int xx, int yy, int attrs)
358 {
359 unsigned char *theChar;
360 unsigned char *where;
361 int i;
362
363 theChar = (unsigned char*)(renderedFont + (ch * vc_rendered_char_size));
364 where = (unsigned char*)(vinfo.v_baseaddr +
365 (yy * CHARHEIGHT * vinfo.v_rowbytes) +
366 (xx));
367
368 if (!attrs) for (i = 0; i < CHARHEIGHT; i++) { /* No attributes ? FLY !!!! */
369 *where = *theChar++;
370
371 where = (unsigned char*)(((unsigned char*)where)+vinfo.v_rowbytes);
372 } else for (i = 0; i < CHARHEIGHT; i++) { /* a little bit slower */
373 unsigned char val = *theChar++, save = val;
374 if (attrs & ATTR_BOLD) { /* bold support */
375 unsigned char mask1 = 0xC0, mask2 = 0x40;
376 int bit = 0;
377 for (bit = 0; bit < 7; bit++) {
378 if ((save & mask1) == mask2)
379 val &= ~mask2;
380 mask1 >>= 1;
381 mask2 >>= 1;
382 }
383 }
384 if (attrs & ATTR_REVERSE) val = ~val;
385 if (attrs & ATTR_UNDER && i == CHARHEIGHT-1) val = ~val;
386 *where = val;
387
388 where = (unsigned char*)(((unsigned char*)where)+vinfo.v_rowbytes);
389 }
390
391 }
392
393 static void vc_paint_char2(unsigned char ch, int xx, int yy, int attrs)
394 {
395 unsigned short *theChar;
396 unsigned short *where;
397 int i;
398
399 theChar = (unsigned short*)(renderedFont + (ch * vc_rendered_char_size));
400 where = (unsigned short*)(vinfo.v_baseaddr +
401 (yy * CHARHEIGHT * vinfo.v_rowbytes) +
402 (xx * 2));
403 if (!attrs) for (i = 0; i < CHARHEIGHT; i++) { /* No attributes ? FLY !!!! */
404 *where = *theChar++;
405
406 where = (unsigned short*)(((unsigned char*)where)+vinfo.v_rowbytes);
407 } else for (i = 0; i < CHARHEIGHT; i++) { /* a little bit slower */
408 unsigned short val = *theChar++, save = val;
409 if (attrs & ATTR_BOLD) { /* bold support */
410 unsigned short mask1 = 0xF000, mask2 = 0x3000;
411 int bit = 0;
412 for (bit = 0; bit < 7; bit++) {
413 if ((save & mask1) == mask2)
414 val &= ~mask2;
415 mask1 >>= 2;
416 mask2 >>= 2;
417 }
418 }
419 if (attrs & ATTR_REVERSE) val = ~val;
420 if (attrs & ATTR_UNDER && i == CHARHEIGHT-1) val = ~val;
421 *where = val;
422
423 where = (unsigned short*)(((unsigned char*)where)+vinfo.v_rowbytes);
424 }
425
426 }
427
428 static void vc_paint_char4(unsigned char ch, int xx, int yy, int attrs)
429 {
430 unsigned long *theChar;
431 unsigned long *where;
432 int i;
433
434 theChar = (unsigned long*)(renderedFont + (ch * vc_rendered_char_size));
435 where = (unsigned long*)(vinfo.v_baseaddr +
436 (yy * CHARHEIGHT * vinfo.v_rowbytes) +
437 (xx * 4));
438
439 if (!attrs) for (i = 0; i < CHARHEIGHT; i++) { /* No attributes ? FLY !!!! */
440 *where = *theChar++;
441
442 where = (unsigned long*)(((unsigned char*)where)+vinfo.v_rowbytes);
443 } else for (i = 0; i < CHARHEIGHT; i++) { /* a little bit slower */
444 unsigned long val = *theChar++, save = val;
445 if (attrs & ATTR_BOLD) { /* bold support */
446 unsigned long mask1 = 0xff000000, mask2 = 0x0F000000;
447 int bit = 0;
448 for (bit = 0; bit < 7; bit++) {
449 if ((save & mask1) == mask2)
450 val &= ~mask2;
451 mask1 >>= 4;
452 mask2 >>= 4;
453 }
454 }
455 if (attrs & ATTR_REVERSE) val = ~val;
456 if (attrs & ATTR_UNDER && i == CHARHEIGHT-1) val = ~val;
457 *where = val;
458
459 where = (unsigned long*)(((unsigned char*)where)+vinfo.v_rowbytes);
460 }
461
462 }
463
464 static void vc_paint_char8c(unsigned char ch, int xx, int yy, int attrs)
465 {
466 unsigned long *theChar;
467 unsigned long *where;
468 int i;
469
470 theChar = (unsigned long*)(renderedFont + (ch * vc_rendered_char_size));
471 where = (unsigned long*)(vinfo.v_baseaddr +
472 (yy * CHARHEIGHT * vinfo.v_rowbytes) +
473 (xx * CHARWIDTH));
474
475 if (!attrs) for (i = 0; i < CHARHEIGHT; i++) { /* No attr? FLY !*/
476 unsigned long *store = where;
477 int x;
478 for (x = 0; x < 2; x++) {
479 unsigned long val = *theChar++;
480 val = (vc_color_back & ~val) | (vc_color_fore & val);
481 *store++ = val;
482 }
483
484 where = (unsigned long*)(((unsigned char*)where)+vinfo.v_rowbytes);
485 } else for (i = 0; i < CHARHEIGHT; i++) { /* a little slower */
486 unsigned long *store = where, lastpixel = 0;
487 int x;
488 for (x = 0 ; x < 2; x++) {
489 unsigned long val = *theChar++, save = val;
490 if (attrs & ATTR_BOLD) { /* bold support */
491 if (lastpixel && !(save & 0xFF000000))
492 val |= 0xff000000;
493 if ((save & 0xFFFF0000) == 0xFF000000)
494 val |= 0x00FF0000;
495 if ((save & 0x00FFFF00) == 0x00FF0000)
496 val |= 0x0000FF00;
497 if ((save & 0x0000FFFF) == 0x0000FF00)
498 val |= 0x000000FF;
499 }
500 if (attrs & ATTR_REVERSE) val = ~val;
501 if (attrs & ATTR_UNDER && i == CHARHEIGHT-1) val = ~val;
502
503 val = (vc_color_back & ~val) | (vc_color_fore & val);
504 *store++ = val;
505 lastpixel = save & 0xff;
506 }
507
508 where = (unsigned long*)(((unsigned char*)where)+vinfo.v_rowbytes);
509 }
510
511 }
512 static void vc_paint_char16c(unsigned char ch, int xx, int yy, int attrs)
513 {
514 unsigned long *theChar;
515 unsigned long *where;
516 int i;
517
518 theChar = (unsigned long*)(renderedFont + (ch * vc_rendered_char_size));
519 where = (unsigned long*)(vinfo.v_baseaddr +
520 (yy * CHARHEIGHT * vinfo.v_rowbytes) +
521 (xx * CHARWIDTH * 2));
522
523 if (!attrs) for (i = 0; i < CHARHEIGHT; i++) { /* No attrs ? FLY ! */
524 unsigned long *store = where;
525 int x;
526 for (x = 0; x < 4; x++) {
527 unsigned long val = *theChar++;
528 val = (vc_color_back & ~val) | (vc_color_fore & val);
529 *store++ = val;
530 }
531
532 where = (unsigned long*)(((unsigned char*)where)+vinfo.v_rowbytes);
533 } else for (i = 0; i < CHARHEIGHT; i++) { /* a little bit slower */
534 unsigned long *store = where, lastpixel = 0;
535 int x;
536 for (x = 0 ; x < 4; x++) {
537 unsigned long val = *theChar++, save = val;
538 if (attrs & ATTR_BOLD) { /* bold support */
539 if (save == 0xFFFF0000) val |= 0xFFFF;
540 else if (lastpixel && !(save & 0xFFFF0000))
541 val |= 0xFFFF0000;
542 }
543 if (attrs & ATTR_REVERSE) val = ~val;
544 if (attrs & ATTR_UNDER && i == CHARHEIGHT-1) val = ~val;
545
546 val = (vc_color_back & ~val) | (vc_color_fore & val);
547
548 *store++ = val;
549 lastpixel = save & 0x7fff;
550 }
551
552 where = (unsigned long*)(((unsigned char*)where)+vinfo.v_rowbytes);
553 }
554
555 }
556 static void vc_paint_char32c(unsigned char ch, int xx, int yy, int attrs)
557 {
558 unsigned long *theChar;
559 unsigned long *where;
560 int i;
561
562 theChar = (unsigned long*)(renderedFont + (ch * vc_rendered_char_size));
563 where = (unsigned long*)(vinfo.v_baseaddr +
564 (yy * CHARHEIGHT * vinfo.v_rowbytes) +
565 (xx * CHARWIDTH * 4));
566
567 if (!attrs) for (i = 0; i < CHARHEIGHT; i++) { /* No attrs ? FLY ! */
568 unsigned long *store = where;
569 int x;
570 for (x = 0; x < 8; x++) {
571 unsigned long val = *theChar++;
572 val = (vc_color_back & ~val) | (vc_color_fore & val);
573 *store++ = val;
574 }
575
576 where = (unsigned long*)(((unsigned char*)where)+vinfo.v_rowbytes);
577 } else for (i = 0; i < CHARHEIGHT; i++) { /* a little slower */
578 unsigned long *store = where, lastpixel = 0;
579 int x;
580 for (x = 0 ; x < 8; x++) {
581 unsigned long val = *theChar++, save = val;
582 if (attrs & ATTR_BOLD) { /* bold support */
583 if (lastpixel && !save)
584 val = 0xFFFFFFFF;
585 }
586 if (attrs & ATTR_REVERSE) val = ~val;
587 if (attrs & ATTR_UNDER && i == CHARHEIGHT-1) val = ~val;
588
589 val = (vc_color_back & ~val) | (vc_color_fore & val);
590 *store++ = val;
591 lastpixel = save;
592 }
593
594 where = (unsigned long*)(((unsigned char*)where)+vinfo.v_rowbytes);
595 }
596
597 }
598
599 /*
600 * That's a plain dumb reverse of the cursor position
601 * It do a binary reverse, so it will not looks good when we have
602 * color support. we'll see that later
603 */
604 static void reversecursor(int xx, int yy)
605 {
606 union {
607 unsigned char *charptr;
608 unsigned short *shortptr;
609 unsigned long *longptr;
610 } where;
611 int line, col;
612
613 where.longptr = (unsigned long*)(vinfo.v_baseaddr +
614 (y * CHARHEIGHT * vinfo.v_rowbytes) +
615 (x /** CHARWIDTH*/ * vinfo.v_depth));
616 for (line = 0; line < CHARHEIGHT; line++) {
617 switch (vinfo.v_depth) {
618 case 1:
619 *where.charptr = ~*where.charptr;
620 break;
621 case 2:
622 *where.shortptr = ~*where.shortptr;
623 break;
624 case 4:
625 *where.longptr = ~*where.longptr;
626 break;
627 /* that code still exists because since characters on the screen are
628 * of different colors that reverse function may not work if the
629 * cursor is on a character that is in a different color that the
630 * current one. When we have buffering, things will work better. MP
631 */
632 #if 1 /*VC_BINARY_REVERSE*/
633 case 8:
634 where.longptr[0] = ~where.longptr[0];
635 where.longptr[1] = ~where.longptr[1];
636 break;
637 case 16:
638 for (col = 0; col < 4; col++)
639 where.longptr[col] = ~where.longptr[col];
640 break;
641 case 32:
642 for (col = 0; col < 8; col++)
643 where.longptr[col] = ~where.longptr[col];
644 break;
645 #else
646 case 8:
647 for (col = 0; col < 8; col++)
648 where.charptr[col] = where.charptr[col] != (vc_color_fore & vc_color_mask) ?
649 vc_color_fore & vc_color_mask : vc_color_back & vc_color_mask;
650 break;
651 case 16:
652 for (col = 0; col < 8; col++)
653 where.shortptr[col] = where.shortptr[col] != (vc_color_fore & vc_color_mask) ?
654 vc_color_fore & vc_color_mask : vc_color_back & vc_color_mask;
655 break;
656 case 32:
657 for (col = 0; col < 8; col++)
658 where.longptr[col] = where.longptr[col] != (vc_color_fore & vc_color_mask) ?
659 vc_color_fore & vc_color_mask : vc_color_back & vc_color_mask;
660 break;
661 #endif
662 }
663 where.charptr += vinfo.v_rowbytes;
664 }
665 }
666
667
668 static void
669 scrollup(int num)
670 {
671 unsigned long *from, *to, linelongs, i, line, rowline, rowscanline;
672
673 linelongs = vinfo.v_rowbytes * CHARHEIGHT / 4;
674 rowline = vinfo.v_rowbytes / 4;
675 rowscanline = vinfo.v_rowscanbytes / 4;
676
677 to = (unsigned long *) vinfo.v_baseaddr + (scrreg_top * linelongs);
678 from = to + (linelongs * num); /* handle multiple line scroll (Michel Pollet) */
679
680 i = (scrreg_bottom - scrreg_top) - num;
681
682 while (i-- > 0) {
683 for (line = 0; line < CHARHEIGHT; line++) {
684 /*
685 * Only copy what is displayed
686 */
687 #if 1
688 bcopy((unsigned int) from, (unsigned int) to,
689 vinfo.v_rowscanbytes);
690 #else
691 video_scroll_up((unsigned int) from,
692 (unsigned int) (from+(vinfo.v_rowscanbytes/4)),
693 (unsigned int) to);
694 #endif
695
696 from += rowline;
697 to += rowline;
698 }
699 }
700
701 /* Now set the freed up lines to the background colour */
702
703
704 to = ((unsigned long *) vinfo.v_baseaddr + (scrreg_top * linelongs))
705 + ((scrreg_bottom - scrreg_top - num) * linelongs);
706
707 for (linelongs = CHARHEIGHT * num; linelongs-- > 0;) {
708 from = to;
709 for (i = 0; i < rowscanline; i++)
710 *to++ = vc_color_back;
711
712 to = from + rowline;
713 }
714
715 }
716
717 static void
718 scrolldown(int num)
719 {
720 unsigned long *from, *to, linelongs, i, line, rowline, rowscanline;
721
722 linelongs = vinfo.v_rowbytes * CHARHEIGHT / 4;
723 rowline = vinfo.v_rowbytes / 4;
724 rowscanline = vinfo.v_rowscanbytes / 4;
725
726
727 to = (unsigned long *) vinfo.v_baseaddr + (linelongs * scrreg_bottom)
728 - (rowline - rowscanline);
729 from = to - (linelongs * num); /* handle multiple line scroll (Michel Pollet) */
730
731 i = (scrreg_bottom - scrreg_top) - num;
732
733 while (i-- > 0) {
734 for (line = 0; line < CHARHEIGHT; line++) {
735 /*
736 * Only copy what is displayed
737 */
738 #if 1
739 bcopy(from-(vinfo.v_rowscanbytes/4), to,
740 vinfo.v_rowscanbytes);
741 #else
742
743 video_scroll_down((unsigned int) from,
744 (unsigned int) (from-(vinfo.v_rowscanbytes/4)),
745 (unsigned int) to);
746 #endif
747
748 from -= rowline;
749 to -= rowline;
750 }
751 }
752
753 /* Now set the freed up lines to the background colour */
754
755 to = (unsigned long *) vinfo.v_baseaddr + (linelongs * scrreg_top);
756
757 for (line = CHARHEIGHT * num; line > 0; line--) {
758 from = to;
759
760 for (i = 0; i < rowscanline; i++)
761 *(to++) = vc_color_back;
762
763 to = from + rowline;
764 }
765
766 }
767
768
769 static void
770 clear_line(int which)
771 {
772 int start, end, i;
773
774 /*
775 * This routine runs extremely slowly. I don't think it's
776 * used all that often, except for To end of line. I'll go
777 * back and speed this up when I speed up the whole vc
778 * module. --LK
779 */
780
781 switch (which) {
782 case 0: /* To end of line */
783 start = x;
784 end = vinfo.v_columns-1;
785 break;
786 case 1: /* To start of line */
787 start = 0;
788 end = x;
789 break;
790 default:
791 case 2: /* Whole line */
792 start = 0;
793 end = vinfo.v_columns-1;
794 break;
795 }
796
797 for (i = start; i <= end; i++) {
798 vc_ops.paintchar(' ', i, y, ATTR_NONE);
799 }
800
801 }
802
803 static void
804 clear_screen(int xx, int yy, int which)
805 {
806 unsigned long *p, *endp, *row;
807 int linelongs, col;
808 int rowline, rowlongs;
809
810 rowline = vinfo.v_rowscanbytes / 4;
811 rowlongs = vinfo.v_rowbytes / 4;
812
813 p = (unsigned long*) vinfo.v_baseaddr;;
814 endp = (unsigned long*) vinfo.v_baseaddr;
815
816 linelongs = vinfo.v_rowbytes * CHARHEIGHT / 4;
817
818 switch (which) {
819 case 0: /* To end of screen */
820 clear_line(0);
821 if (y < vinfo.v_rows - 1) {
822 p += (y + 1) * linelongs;
823 endp += rowlongs * vinfo.v_height;
824 }
825 break;
826 case 1: /* To start of screen */
827 clear_line(1);
828 if (y > 1) {
829 endp += (y + 1) * linelongs;
830 }
831 break;
832 case 2: /* Whole screen */
833 endp += rowlongs * vinfo.v_height;
834 break;
835 }
836
837 for (row = p ; row < endp ; row += rowlongs) {
838 for (col = 0; col < rowline; col++)
839 *(row+col) = vc_color_back;
840 }
841
842 }
843
844 static void
845 reset_tabs(void)
846 {
847 int i;
848
849 for (i = 0; i<= vinfo.v_columns; i++) {
850 tab_stops[i] = ((i % 8) == 0);
851 }
852
853 }
854
855 static void
856 vt100_reset(void)
857 {
858 reset_tabs();
859 scrreg_top = 0;
860 scrreg_bottom = vinfo.v_rows;
861 attr = ATTR_NONE;
862 vc_charset[0] = vc_charset[1] = 0;
863 vc_charset_select = 0;
864 vc_wrap_mode = 1;
865 vc_relative_origin = 0;
866 vc_color_set(VC_RESET_BACKGROUND);
867 vc_color_set(VC_RESET_FOREGROUND);
868
869 }
870
871 static void
872 putc_normal(unsigned char ch)
873 {
874 switch (ch) {
875 case '\a': /* Beep */
876 {
877 if ( FALSE && !IS_TEXT_MODE ) {
878 /*
879 * No sound hardware, invert the screen twice instead
880 */
881 unsigned long *ptr;
882 int i, j;
883 /* XOR the screen twice */
884 for (i = 0; i < 2 ; i++) {
885 /* For each row, xor the scanbytes */
886 for (ptr = (unsigned long*)vinfo.v_baseaddr;
887 ptr < (unsigned long*)(vinfo.v_baseaddr +
888 (vinfo.v_height * vinfo.v_rowbytes));
889 ptr += (vinfo.v_rowbytes /
890 sizeof (unsigned long*)))
891 for (j = 0;
892 j < vinfo.v_rowscanbytes /
893 sizeof (unsigned long*);
894 j++)
895 *(ptr+j) =~*(ptr+j);
896 }
897 }
898 }
899 break;
900
901 case 127: /* Delete */
902 case '\b': /* Backspace */
903 if (hanging_cursor) {
904 hanging_cursor = 0;
905 } else
906 if (x > 0) {
907 x--;
908 }
909 break;
910 case '\t': /* Tab */
911 while (x < vinfo.v_columns && !tab_stops[++x]);
912 if (x >= vinfo.v_columns)
913 x = vinfo.v_columns-1;
914 break;
915 case 0x0b:
916 case 0x0c:
917 case '\n': /* Line feed */
918 if (y >= scrreg_bottom -1 ) {
919 vc_ops.scrollup(1);
920 y = scrreg_bottom - 1;
921 } else {
922 y++;
923 }
924 /*break; Pass thru */
925 case '\r': /* Carriage return */
926 x = 0;
927 hanging_cursor = 0;
928 break;
929 case 0x0e: /* Select G1 charset (Control-N) */
930 vc_charset_select = 1;
931 break;
932 case 0x0f: /* Select G0 charset (Control-O) */
933 vc_charset_select = 0;
934 break;
935 case 0x18 : /* CAN : cancel */
936 case 0x1A : /* like cancel */
937 /* well, i do nothing here, may be later */
938 break;
939 case '\033': /* Escape */
940 vt100state = ESesc;
941 hanging_cursor = 0;
942 break;
943 default:
944 if (ch >= ' ') {
945 if (hanging_cursor) {
946 x = 0;
947 if (y >= scrreg_bottom -1 ) {
948 vc_ops.scrollup(1);
949 y = scrreg_bottom - 1;
950 } else {
951 y++;
952 }
953 hanging_cursor = 0;
954 }
955 vc_ops.paintchar((ch >= 0x60 && ch <= 0x7f) ? ch + vc_charset[vc_charset_select]
956 : ch, x, y, attr);
957 if (x == vinfo.v_columns - 1) {
958 hanging_cursor = vc_wrap_mode;
959 } else {
960 x++;
961 }
962 }
963 break;
964 }
965
966 }
967
968 static void
969 putc_esc(unsigned char ch)
970 {
971 vt100state = ESnormal;
972
973 switch (ch) {
974 case '[':
975 vt100state = ESsquare;
976 break;
977 case 'c': /* Reset terminal */
978 vt100_reset();
979 vc_ops.clear_screen(x, y, 2);
980 x = y = 0;
981 break;
982 case 'D': /* Line feed */
983 case 'E':
984 if (y >= scrreg_bottom -1) {
985 vc_ops.scrollup(1);
986 y = scrreg_bottom - 1;
987 } else {
988 y++;
989 }
990 if (ch == 'E') x = 0;
991 break;
992 case 'H': /* Set tab stop */
993 tab_stops[x] = 1;
994 break;
995 case 'M': /* Cursor up */
996 if (y <= scrreg_top) {
997 vc_ops.scrolldown(1);
998 y = scrreg_top;
999 } else {
1000 y--;
1001 }
1002 break;
1003 case '>':
1004 vt100_reset();
1005 break;
1006 case '7': /* Save cursor */
1007 savex = x;
1008 savey = y;
1009 saveattr = attr;
1010 vc_save_charset_s = vc_charset_select;
1011 vc_charset_save[0] = vc_charset[0];
1012 vc_charset_save[1] = vc_charset[1];
1013 break;
1014 case '8': /* Restore cursor */
1015 x = savex;
1016 y = savey;
1017 attr = saveattr;
1018 vc_charset_select = vc_save_charset_s;
1019 vc_charset[0] = vc_charset_save[0];
1020 vc_charset[1] = vc_charset_save[1];
1021 break;
1022 case 'Z': /* return terminal ID */
1023 break;
1024 case '#': /* change characters height */
1025 vt100state = EScharsize;
1026 break;
1027 case '(':
1028 vt100state = ESsetG0;
1029 break;
1030 case ')': /* character set sequence */
1031 vt100state = ESsetG1;
1032 break;
1033 case '=':
1034 break;
1035 default:
1036 /* Rest not supported */
1037 break;
1038 }
1039
1040 }
1041
1042 static void
1043 putc_askcmd(unsigned char ch)
1044 {
1045 if (ch >= '0' && ch <= '9') {
1046 par[numpars] = (10*par[numpars]) + (ch-'0');
1047 return;
1048 }
1049 vt100state = ESnormal;
1050
1051 switch (par[0]) {
1052 case 6:
1053 vc_relative_origin = ch == 'h';
1054 break;
1055 case 7: /* wrap around mode h=1, l=0*/
1056 vc_wrap_mode = ch == 'h';
1057 break;
1058 default:
1059 break;
1060 }
1061
1062 }
1063
1064 static void
1065 putc_charsizecmd(unsigned char ch)
1066 {
1067 vt100state = ESnormal;
1068
1069 switch (ch) {
1070 case '3' :
1071 case '4' :
1072 case '5' :
1073 case '6' :
1074 break;
1075 case '8' : /* fill 'E's */
1076 {
1077 int xx, yy;
1078 for (yy = 0; yy < vinfo.v_rows; yy++)
1079 for (xx = 0; xx < vinfo.v_columns; xx++)
1080 vc_ops.paintchar('E', xx, yy, ATTR_NONE);
1081 }
1082 break;
1083 }
1084
1085 }
1086
1087 static void
1088 putc_charsetcmd(int charset, unsigned char ch)
1089 {
1090 vt100state = ESnormal;
1091
1092 switch (ch) {
1093 case 'A' :
1094 case 'B' :
1095 default:
1096 vc_charset[charset] = 0;
1097 break;
1098 case '0' : /* Graphic characters */
1099 case '2' :
1100 vc_charset[charset] = 0x21;
1101 break;
1102 }
1103
1104 }
1105
1106 static void
1107 putc_gotpars(unsigned char ch)
1108 {
1109 int i;
1110
1111 if (ch < ' ') {
1112 /* special case for vttest for handling cursor
1113 movement in escape sequences */
1114 putc_normal(ch);
1115 vt100state = ESgotpars;
1116 return;
1117 }
1118 vt100state = ESnormal;
1119 switch (ch) {
1120 case 'A': /* Up */
1121 y -= par[0] ? par[0] : 1;
1122 if (y < scrreg_top)
1123 y = scrreg_top;
1124 break;
1125 case 'B': /* Down */
1126 y += par[0] ? par[0] : 1;
1127 if (y >= scrreg_bottom)
1128 y = scrreg_bottom - 1;
1129 break;
1130 case 'C': /* Right */
1131 x += par[0] ? par[0] : 1;
1132 if (x >= vinfo.v_columns)
1133 x = vinfo.v_columns-1;
1134 break;
1135 case 'D': /* Left */
1136 x -= par[0] ? par[0] : 1;
1137 if (x < 0)
1138 x = 0;
1139 break;
1140 case 'H': /* Set cursor position */
1141 case 'f':
1142 x = par[1] ? par[1] - 1 : 0;
1143 y = par[0] ? par[0] - 1 : 0;
1144 if (vc_relative_origin)
1145 y += scrreg_top;
1146 hanging_cursor = 0;
1147 break;
1148 case 'X': /* clear p1 characters */
1149 if (numpars) {
1150 int i;
1151 for (i = x; i < x + par[0]; i++)
1152 vc_ops.paintchar(' ', i, y, ATTR_NONE);
1153 }
1154 break;
1155 case 'J': /* Clear part of screen */
1156 vc_ops.clear_screen(x, y, par[0]);
1157 break;
1158 case 'K': /* Clear part of line */
1159 clear_line(par[0]);
1160 break;
1161 case 'g': /* tab stops */
1162 switch (par[0]) {
1163 case 1:
1164 case 2: /* reset tab stops */
1165 /* reset_tabs(); */
1166 break;
1167 case 3: /* Clear every tabs */
1168 {
1169 int i;
1170
1171 for (i = 0; i <= vinfo.v_columns; i++)
1172 tab_stops[i] = 0;
1173 }
1174 break;
1175 case 0:
1176 tab_stops[x] = 0;
1177 break;
1178 }
1179 break;
1180 case 'm': /* Set attribute */
1181 for (i = 0; i < numpars; i++) {
1182 switch (par[i]) {
1183 case 0:
1184 attr = ATTR_NONE;
1185 vc_color_set(VC_RESET_BACKGROUND);
1186 vc_color_set(VC_RESET_FOREGROUND);
1187 break;
1188 case 1:
1189 attr |= ATTR_BOLD;
1190 break;
1191 case 4:
1192 attr |= ATTR_UNDER;
1193 break;
1194 case 7:
1195 attr |= ATTR_REVERSE;
1196 break;
1197 case 22:
1198 attr &= ~ATTR_BOLD;
1199 break;
1200 case 24:
1201 attr &= ~ATTR_UNDER;
1202 break;
1203 case 27:
1204 attr &= ~ATTR_REVERSE;
1205 break;
1206 case 5:
1207 case 25: /* blink/no blink */
1208 break;
1209 default:
1210 vc_color_set(par[i]);
1211 break;
1212 }
1213 }
1214 break;
1215 case 'r': /* Set scroll region */
1216 x = y = 0;
1217 /* ensure top < bottom, and both within limits */
1218 if ((numpars > 0) && (par[0] < vinfo.v_rows)) {
1219 scrreg_top = par[0] ? par[0] - 1 : 0;
1220 if (scrreg_top < 0)
1221 scrreg_top = 0;
1222 } else {
1223 scrreg_top = 0;
1224 }
1225 if ((numpars > 1) && (par[1] <= vinfo.v_rows) && (par[1] > par[0])) {
1226 scrreg_bottom = par[1];
1227 if (scrreg_bottom > vinfo.v_rows)
1228 scrreg_bottom = vinfo.v_rows;
1229 } else {
1230 scrreg_bottom = vinfo.v_rows;
1231 }
1232 if (vc_relative_origin)
1233 y = scrreg_top;
1234 break;
1235 }
1236
1237 }
1238
1239 static void
1240 putc_getpars(unsigned char ch)
1241 {
1242 if (ch == '?') {
1243 vt100state = ESask;
1244 return;
1245 }
1246 if (ch == '[') {
1247 vt100state = ESnormal;
1248 /* Not supported */
1249 return;
1250 }
1251 if (ch == ';' && numpars < MAXPARS - 1) {
1252 numpars++;
1253 } else
1254 if (ch >= '0' && ch <= '9') {
1255 par[numpars] *= 10;
1256 par[numpars] += ch - '0';
1257 } else {
1258 numpars++;
1259 vt100state = ESgotpars;
1260 putc_gotpars(ch);
1261 }
1262 }
1263
1264 static void
1265 putc_square(unsigned char ch)
1266 {
1267 int i;
1268
1269 for (i = 0; i < MAXPARS; i++) {
1270 par[i] = 0;
1271 }
1272
1273 numpars = 0;
1274 vt100state = ESgetpars;
1275
1276 putc_getpars(ch);
1277
1278 }
1279
1280 void
1281 vc_putchar(char ch)
1282 {
1283 if (!ch) {
1284 return; /* ignore null characters */
1285 }
1286
1287 switch (vt100state) {
1288 default:vt100state = ESnormal; /* FALLTHROUGH */
1289 case ESnormal:
1290 putc_normal(ch);
1291 break;
1292 case ESesc:
1293 putc_esc(ch);
1294 break;
1295 case ESsquare:
1296 putc_square(ch);
1297 break;
1298 case ESgetpars:
1299 putc_getpars(ch);
1300 break;
1301 case ESgotpars:
1302 putc_gotpars(ch);
1303 break;
1304 case ESask:
1305 putc_askcmd(ch);
1306 break;
1307 case EScharsize:
1308 putc_charsizecmd(ch);
1309 break;
1310 case ESsetG0:
1311 putc_charsetcmd(0, ch);
1312 break;
1313 case ESsetG1:
1314 putc_charsetcmd(1, ch);
1315 break;
1316 }
1317
1318 if (x >= vinfo.v_columns) {
1319 x = vinfo.v_columns - 1;
1320 }
1321 if (x < 0) {
1322 x = 0;
1323 }
1324 if (y >= vinfo.v_rows) {
1325 y = vinfo.v_rows - 1;
1326 }
1327 if (y < 0) {
1328 y = 0;
1329 }
1330
1331 }
1332
1333 /*
1334 * Actually draws the buffer, handle the jump scroll
1335 */
1336 void vc_flush_forward_buffer(void)
1337 {
1338 if (vc_forward_buffer_size) {
1339 int start = 0;
1340 vc_ops.hide_cursor(x, y);
1341 do {
1342 int i;
1343 int plaintext = 1;
1344 int drawlen = start;
1345 int jump = 0;
1346 int param = 0, changebackground = 0;
1347 enum vt100state_e vtState = vt100state;
1348 /*
1349 * In simple words, here we're pre-parsing the text to look for
1350 * + Newlines, for computing jump scroll
1351 * + /\033\[[0-9;]*]m/ to continue on
1352 * any other sequence will stop. We don't want to have cursor
1353 * movement escape sequences while we're trying to pre-scroll
1354 * the screen.
1355 * We have to be extra carefull about the sequences that changes
1356 * the background color to prevent scrolling in those
1357 * particular cases.
1358 * That parsing was added to speed up 'man' and 'color-ls' a
1359 * zillion time (at least). It's worth it, trust me.
1360 * (mail Nick Stephen for a True Performance Graph)
1361 * Michel Pollet
1362 */
1363 for (i = start; i < vc_forward_buffer_size && plaintext; i++) {
1364 drawlen++;
1365 switch (vtState) {
1366 case ESnormal:
1367 switch (vc_forward_buffer[i]) {
1368 case '\033':
1369 vtState = ESesc;
1370 break;
1371 case '\n':
1372 jump++;
1373 break;
1374 }
1375 break;
1376 case ESesc:
1377 switch (vc_forward_buffer[i]) {
1378 case '[':
1379 vtState = ESgetpars;
1380 param = 0;
1381 changebackground = 0;
1382 break;
1383 default:
1384 plaintext = 0;
1385 break;
1386 }
1387 break;
1388 case ESgetpars:
1389 if ((vc_forward_buffer[i] >= '0' &&
1390 vc_forward_buffer[i] <= '9') ||
1391 vc_forward_buffer[i] == ';') {
1392 if (vc_forward_buffer[i] >= '0' &&
1393 vc_forward_buffer[i] <= '9')
1394 param = (param*10)+(vc_forward_buffer[i]-'0');
1395 else {
1396 if (param >= 40 && param <= 47)
1397 changebackground = 1;
1398 if (!vc_normal_background &&
1399 !param)
1400 changebackground = 1;
1401 param = 0;
1402 }
1403 break; /* continue on */
1404 }
1405 vtState = ESgotpars;
1406 /* fall */
1407 case ESgotpars:
1408 switch (vc_forward_buffer[i]) {
1409 case 'm':
1410 vtState = ESnormal;
1411 if (param >= 40 && param <= 47)
1412 changebackground = 1;
1413 if (!vc_normal_background &&
1414 !param)
1415 changebackground = 1;
1416 if (changebackground) {
1417 plaintext = 0;
1418 jump = 0;
1419 /* REALLY don't jump */
1420 }
1421 /* Yup ! we've got it */
1422 break;
1423 default:
1424 plaintext = 0;
1425 break;
1426 }
1427 break;
1428 default:
1429 plaintext = 0;
1430 break;
1431 }
1432
1433 }
1434
1435 /*
1436 * Then we look if it would be appropriate to forward jump
1437 * the screen before drawing
1438 */
1439 if (jump && (scrreg_bottom - scrreg_top) > 2) {
1440 jump -= scrreg_bottom - y - 1;
1441 if (jump > 0 ) {
1442 if (jump >= scrreg_bottom - scrreg_top)
1443 jump = scrreg_bottom - scrreg_top -1;
1444 y -= jump;
1445 vc_ops.scrollup(jump);
1446 }
1447 }
1448 /*
1449 * and we draw what we've found to the parser
1450 */
1451 for (i = start; i < drawlen; i++)
1452 vc_putchar(vc_forward_buffer[start++]);
1453 /*
1454 * Continue sending characters to the parser until we're sure we're
1455 * back on normal characters.
1456 */
1457 for (i = start; i < vc_forward_buffer_size &&
1458 vt100state != ESnormal ; i++)
1459 vc_putchar(vc_forward_buffer[start++]);
1460 /* Then loop again if there still things to draw */
1461 } while (start < vc_forward_buffer_size);
1462 vc_forward_buffer_size = 0;
1463 vc_ops.show_cursor(x, y);
1464 }
1465 }
1466
1467 int
1468 vcputc(int l, int u, int c)
1469 {
1470 if ( vc_initialized )
1471 {
1472 vc_store_char(c);
1473 vc_flush_forward_buffer();
1474 }
1475 return 0;
1476 }
1477
1478 /*
1479 * Immediate character display.. kernel printf uses this. Make sure
1480 * pre-clock printfs get flushed and that panics get fully displayed.
1481 */
1482
1483 void cnputc(char ch)
1484 {
1485 vcputc(0, 0, ch);
1486 }
1487
1488 /*
1489 * Store characters to be drawn 'later', handle overflows
1490 */
1491
1492 void
1493 vc_store_char(unsigned char c)
1494 {
1495
1496 /* Either we're really buffering stuff or we're not yet because
1497 * the probe hasn't been done. If we're not, then we can only
1498 * ever have a maximum of one character in the buffer waiting to
1499 * be flushed
1500 */
1501
1502 vc_forward_buffer[vc_forward_buffer_size++] = (unsigned char)c;
1503
1504 switch (vc_forward_buffer_size) {
1505 case 1:
1506 /* If we're adding the first character to the buffer,
1507 * start the timer, otherwise it is already running.
1508 */
1509 break;
1510 case VC_MAX_FORWARD_SIZE:
1511 vc_flush_forward_buffer();
1512 break;
1513 default:
1514 /*
1515 * the character will be flushed on timeout
1516 */
1517 break;
1518 }
1519 }
1520
1521 static void
1522 vc_initialize(struct vc_info * vinfo_p)
1523 {
1524 vinfo.v_rows = vinfo.v_height / CHARHEIGHT;
1525 vinfo.v_columns = vinfo.v_width / CHARWIDTH;
1526
1527 if (vinfo.v_depth >= 8) {
1528 vinfo.v_rowscanbytes = (vinfo.v_depth / 8) * vinfo.v_width;
1529 } else {
1530 vinfo.v_rowscanbytes = vinfo.v_width / (8 / vinfo.v_depth);
1531 }
1532
1533 vc_render_font(1, vinfo.v_depth);
1534 vc_color_mask = vc_color_depth_masks[vc_color_index_table[vinfo.v_depth]];
1535 vt100_reset();
1536 switch (vinfo.v_depth) {
1537 default:
1538 case 1:
1539 vc_ops.paintchar = vc_paint_char1;
1540 break;
1541 case 2:
1542 vc_ops.paintchar = vc_paint_char2;
1543 break;
1544 case 4:
1545 vc_ops.paintchar = vc_paint_char4;
1546 break;
1547 case 8:
1548 vc_ops.paintchar = vc_paint_char8c;
1549 break;
1550 case 16:
1551 vc_ops.paintchar = vc_paint_char16c;
1552 break;
1553 case 32:
1554 vc_ops.paintchar = vc_paint_char32c;
1555 break;
1556 }
1557 }
1558
1559 void
1560 vcattach(void)
1561 {
1562 if (vinfo.v_depth >= 8)
1563 printf("\033[31mC\033[32mO\033[33mL\033[34mO\033[35mR\033[0m ");
1564 printf("video console at 0x%lx (%ldx%ldx%ld)\n", vinfo.v_baseaddr,
1565 vinfo.v_width, vinfo.v_height, vinfo.v_depth);
1566
1567 #if 0 // XXX - FIXME
1568 /*
1569 * Added for the buffering and jump scrolling
1570 */
1571 /* Init our lock */
1572 simple_lock_init(&vc_forward_lock, ETAP_IO_TTY);
1573
1574 vc_forward_buffer_enabled = 1;
1575 #else // FIXME TOO!!!
1576 /* Init our lock */
1577 simple_lock_init(&vc_forward_lock, ETAP_IO_TTY);
1578 #endif
1579 }
1580
1581
1582 struct vc_progress_element {
1583 unsigned int version;
1584 unsigned int flags;
1585 unsigned int time;
1586 unsigned char count;
1587 unsigned char res[3];
1588 int width;
1589 int height;
1590 int dx;
1591 int dy;
1592 int transparent;
1593 unsigned int res2[3];
1594 unsigned char data[0];
1595 };
1596 typedef struct vc_progress_element vc_progress_element;
1597
1598 static vc_progress_element * vc_progress;
1599 static const unsigned char * vc_progress_data;
1600 static const unsigned char * vc_progress_alpha;
1601 static boolean_t vc_progress_enable;
1602 static const unsigned char * vc_clut;
1603 static const unsigned char * vc_clut8;
1604 static unsigned int vc_progress_tick;
1605 static boolean_t vc_graphics_mode;
1606 static boolean_t vc_acquired;
1607 static boolean_t vc_need_clear;
1608 static boolean_t vc_needsave;
1609 static vm_address_t vc_saveunder;
1610 static vm_size_t vc_saveunder_len;
1611
1612 void vc_blit_rect_8c( int x, int y,
1613 int width, int height,
1614 const unsigned char * dataPtr, const unsigned char * alphaPtr,
1615 unsigned char * backPtr, boolean_t save )
1616 {
1617 volatile unsigned char * dst;
1618 int line, col;
1619 unsigned char data;
1620
1621 dst = (unsigned char *)(vinfo.v_baseaddr +
1622 (y * vinfo.v_rowbytes) +
1623 (x));
1624
1625 dst = (unsigned char *)(vinfo.v_baseaddr +
1626 (y * vinfo.v_rowbytes) +
1627 (x));
1628
1629 for( line = 0; line < height; line++) {
1630 for( col = 0; col < width; col++)
1631 *(dst + col) = *dataPtr++;
1632 dst = (volatile unsigned char *) (((int)dst) + vinfo.v_rowbytes);
1633 }
1634 }
1635
1636 void vc_blit_rect_16( int x, int y,
1637 int width, int height,
1638 const unsigned char * dataPtr, const unsigned char * alphaPtr,
1639 unsigned short * backPtr, boolean_t save )
1640 {
1641 volatile unsigned short * dst;
1642 int line, col;
1643 unsigned int data, index, alpha, back;
1644
1645 dst = (volatile unsigned short *)(vinfo.v_baseaddr +
1646 (y * vinfo.v_rowbytes) +
1647 (x * 2));
1648
1649 for( line = 0; line < height; line++) {
1650 for( col = 0; col < width; col++) {
1651 index = *dataPtr++;
1652 index *= 3;
1653
1654 if( alphaPtr && backPtr && (alpha = *alphaPtr++)) {
1655
1656 data = 0;
1657 if( vc_clut[index + 0] > alpha)
1658 data |= (((vc_clut[index + 0] - alpha) & 0xf8) << 7);
1659 if( vc_clut[index + 1] > alpha)
1660 data |= (((vc_clut[index + 1] - alpha) & 0xf8) << 2);
1661 if( vc_clut[index + 2] > alpha)
1662 data |= (((vc_clut[index + 2] - alpha) & 0xf8) >> 3);
1663
1664 if( save) {
1665 back = *(dst + col);
1666 alpha >>= 3;
1667 back = (((((back & 0x7c1f) * alpha) + 0x7c1f) >> 5) & 0x7c1f)
1668 | (((((back & 0x03e0) * alpha) + 0x03e0) >> 5) & 0x03e0);
1669 *backPtr++ = back;
1670 } else
1671 back = *backPtr++;
1672
1673 data += back;
1674
1675 } else
1676 data = ( (0xf8 & (vc_clut[index + 0])) << 7)
1677 | ( (0xf8 & (vc_clut[index + 1])) << 2)
1678 | ( (0xf8 & (vc_clut[index + 2])) >> 3);
1679
1680 *(dst + col) = data;
1681 }
1682 dst = (volatile unsigned short *) (((int)dst) + vinfo.v_rowbytes);
1683 }
1684 }
1685
1686 void vc_blit_rect_32( unsigned int x, unsigned int y,
1687 unsigned int width, unsigned int height,
1688 const unsigned char * dataPtr, const unsigned char * alphaPtr,
1689 unsigned int * backPtr, boolean_t save )
1690 {
1691 volatile unsigned int * dst;
1692 int line, col;
1693 unsigned int data, index, alpha, back;
1694
1695 dst = (volatile unsigned int *) (vinfo.v_baseaddr +
1696 (y * vinfo.v_rowbytes) +
1697 (x * 4));
1698
1699 for( line = 0; line < height; line++) {
1700 for( col = 0; col < width; col++) {
1701 index = *dataPtr++;
1702 index *= 3;
1703 if( alphaPtr && backPtr && (alpha = *alphaPtr++)) {
1704
1705 data = 0;
1706 if( vc_clut[index + 0] > alpha)
1707 data |= ((vc_clut[index + 0] - alpha) << 16);
1708 if( vc_clut[index + 1] > alpha)
1709 data |= ((vc_clut[index + 1] - alpha) << 8);
1710 if( vc_clut[index + 2] > alpha)
1711 data |= ((vc_clut[index + 2] - alpha));
1712
1713 if( save) {
1714 back = *(dst + col);
1715 back = (((((back & 0x00ff00ff) * alpha) + 0x00ff00ff) >> 8) & 0x00ff00ff)
1716 | (((((back & 0x0000ff00) * alpha) + 0x0000ff00) >> 8) & 0x0000ff00);
1717 *backPtr++ = back;
1718 } else
1719 back = *backPtr++;
1720
1721 data += back;
1722
1723 } else
1724 data = (vc_clut[index + 0] << 16)
1725 | (vc_clut[index + 1] << 8)
1726 | (vc_clut[index + 2]);
1727
1728 *(dst + col) = data;
1729 }
1730 dst = (volatile unsigned int *) (((int)dst) + vinfo.v_rowbytes);
1731 }
1732 }
1733
1734 void vc_blit_rect( unsigned int x, unsigned int y,
1735 unsigned int width, unsigned int height,
1736 const unsigned char * dataPtr, const unsigned char * alphaPtr,
1737 vm_address_t backBuffer, boolean_t save )
1738 {
1739 if(!vinfo.v_baseaddr)
1740 return;
1741
1742 switch( vinfo.v_depth) {
1743 case 8:
1744 if( vc_clut8 == vc_clut)
1745 vc_blit_rect_8c( x, y, width, height, dataPtr, alphaPtr, (unsigned char *) backBuffer, save );
1746 break;
1747 case 16:
1748 vc_blit_rect_16( x, y, width, height, dataPtr, alphaPtr, (unsigned short *) backBuffer, save );
1749 break;
1750 case 32:
1751 vc_blit_rect_32( x, y, width, height, dataPtr, alphaPtr, (unsigned int *) backBuffer, save );
1752 break;
1753 }
1754 }
1755
1756 void vc_progress_task( void * arg )
1757 {
1758 spl_t s;
1759 int count = (int) arg;
1760 int x, y, width, height;
1761 const unsigned char * data;
1762
1763 s = splhigh();
1764 simple_lock(&vc_forward_lock);
1765
1766 if( vc_progress_enable) {
1767
1768 count++;
1769 if( count >= vc_progress->count)
1770 count = 0;
1771
1772 width = vc_progress->width;
1773 height = vc_progress->height;
1774 x = vc_progress->dx;
1775 y = vc_progress->dy;
1776 data = vc_progress_data;
1777 data += count * width * height;
1778 if( 1 & vc_progress->flags) {
1779 x += ((vinfo.v_width - width) / 2);
1780 y += ((vinfo.v_height - height) / 2);
1781 }
1782 vc_blit_rect( x, y, width, height,
1783 data, vc_progress_alpha, vc_saveunder, vc_needsave );
1784 vc_needsave = FALSE;
1785
1786 timeout( vc_progress_task, (void *) count,
1787 vc_progress_tick );
1788 }
1789 simple_unlock(&vc_forward_lock);
1790 splx(s);
1791 }
1792
1793 void vc_display_icon( vc_progress_element * desc,
1794 const unsigned char * data )
1795 {
1796 int x, y, width, height;
1797
1798 if( vc_acquired && vc_graphics_mode && vc_clut) {
1799
1800 width = desc->width;
1801 height = desc->height;
1802 x = desc->dx;
1803 y = desc->dy;
1804 if( 1 & desc->flags) {
1805 x += ((vinfo.v_width - width) / 2);
1806 y += ((vinfo.v_height - height) / 2);
1807 }
1808 vc_blit_rect( x, y, width, height, data, NULL, (vm_address_t) NULL, FALSE );
1809 }
1810 }
1811
1812 boolean_t
1813 vc_progress_set( boolean_t enable, unsigned int initial_tick )
1814 {
1815 spl_t s;
1816 vm_address_t saveBuf = 0;
1817 vm_size_t saveLen = 0;
1818
1819 if( !vc_progress)
1820 return( FALSE );
1821
1822 if( enable) {
1823 saveLen = vc_progress->width * vc_progress->height * vinfo.v_depth / 8;
1824 saveBuf = kalloc( saveLen );
1825 }
1826
1827 s = splhigh();
1828 simple_lock(&vc_forward_lock);
1829
1830 if( vc_progress_enable != enable) {
1831 vc_progress_enable = enable;
1832 if( enable) {
1833 vc_needsave = TRUE;
1834 vc_saveunder = saveBuf;
1835 vc_saveunder_len = saveLen;
1836 saveBuf = 0;
1837 saveLen = 0;
1838 timeout(vc_progress_task, (void *) 0,
1839 initial_tick );
1840 }
1841 else {
1842 if( vc_saveunder) {
1843 saveBuf = vc_saveunder;
1844 saveLen = vc_saveunder_len;
1845 vc_saveunder = 0;
1846 vc_saveunder_len = 0;
1847 }
1848 untimeout( vc_progress_task, (void *) 0 );
1849 }
1850 }
1851
1852 simple_unlock(&vc_forward_lock);
1853 splx(s);
1854
1855 if( saveBuf)
1856 kfree( saveBuf, saveLen );
1857
1858 return( TRUE );
1859 }
1860
1861
1862 boolean_t
1863 vc_progress_initialize( vc_progress_element * desc,
1864 const unsigned char * data,
1865 const unsigned char * clut )
1866 {
1867 if( (!clut) || (!desc) || (!data))
1868 return( FALSE );
1869 vc_clut = clut;
1870 vc_clut8 = clut;
1871
1872 vc_progress = desc;
1873 vc_progress_data = data;
1874 if( 2 & vc_progress->flags)
1875 vc_progress_alpha = vc_progress_data
1876 + vc_progress->count * vc_progress->width * vc_progress->height;
1877 else
1878 vc_progress_alpha = NULL;
1879 vc_progress_tick = vc_progress->time * hz / 1000;
1880
1881 return( TRUE );
1882 }
1883
1884 extern int disableConsoleOutput;
1885
1886 void vc_clear_screen( void )
1887 {
1888 vc_ops.hide_cursor(x, y);
1889 vt100_reset();
1890 x = y = 0;
1891 vc_ops.clear_screen(x, y, 2);
1892 vc_ops.show_cursor(x, y);
1893 };
1894
1895 void
1896 initialize_screen(Boot_Video * boot_vinfo, int op)
1897 {
1898 if ( boot_vinfo )
1899 {
1900 vinfo.v_width = boot_vinfo->v_width;
1901 vinfo.v_height = boot_vinfo->v_height;
1902 vinfo.v_depth = boot_vinfo->v_depth;
1903 vinfo.v_rowbytes = boot_vinfo->v_rowBytes;
1904 vinfo.v_baseaddr = boot_vinfo->v_baseAddr;
1905 vinfo.v_type = boot_vinfo->v_display;
1906
1907 if ( IS_TEXT_MODE )
1908 {
1909 // Text mode setup by the booter.
1910
1911 vc_ops.initialize = tc_initialize;
1912 vc_ops.paintchar = tc_putchar;
1913 vc_ops.scrolldown = tc_scrolldown;
1914 vc_ops.scrollup = tc_scrollup;
1915 vc_ops.clear_screen = tc_clear_screen;
1916 vc_ops.hide_cursor = tc_hide_cursor;
1917 vc_ops.show_cursor = tc_show_cursor;
1918 vc_ops.update_color = tc_update_color;
1919 }
1920 else
1921 {
1922 // Graphics mode setup by the booter.
1923
1924 vc_ops.initialize = vc_initialize;
1925 vc_ops.paintchar = 0;
1926 vc_ops.scrolldown = scrolldown;
1927 vc_ops.scrollup = scrollup;
1928 vc_ops.clear_screen = clear_screen;
1929 vc_ops.hide_cursor = reversecursor;
1930 vc_ops.show_cursor = reversecursor;
1931 vc_ops.update_color = 0;
1932 }
1933
1934 vc_ops.initialize(&vinfo);
1935
1936 // vc_clear_screen();
1937
1938 vc_initialized = 1;
1939 }
1940
1941 switch ( op ) {
1942
1943 case kPEGraphicsMode:
1944 vc_graphics_mode = TRUE;
1945 disableConsoleOutput = TRUE;
1946 vc_acquired = TRUE;
1947 break;
1948
1949 case kPETextMode:
1950 vc_graphics_mode = FALSE;
1951 disableConsoleOutput = FALSE;
1952 vc_acquired = TRUE;
1953 vc_clear_screen();
1954 break;
1955
1956 case kPETextScreen:
1957 vc_progress_set( FALSE, 0 );
1958 disableConsoleOutput = FALSE;
1959 if( vc_need_clear) {
1960 vc_need_clear = FALSE;
1961 vc_clear_screen();
1962 }
1963 break;
1964
1965 case kPEEnableScreen:
1966 if ( vc_acquired) {
1967 if( vc_graphics_mode)
1968 vc_progress_set( TRUE, vc_progress_tick );
1969 else
1970 vc_clear_screen();
1971 }
1972 break;
1973
1974 case kPEDisableScreen:
1975 vc_progress_set( FALSE, 0 );
1976 break;
1977
1978 case kPEAcquireScreen:
1979 vc_need_clear = (FALSE == vc_acquired);
1980 vc_acquired = TRUE;
1981 vc_progress_set( vc_graphics_mode, vc_need_clear ? 2 * hz : 0 );
1982 disableConsoleOutput = vc_graphics_mode;
1983 if( vc_need_clear && !vc_graphics_mode) {
1984 vc_need_clear = FALSE;
1985 vc_clear_screen();
1986 }
1987 break;
1988
1989 case kPEReleaseScreen:
1990 vc_acquired = FALSE;
1991 vc_progress_set( FALSE, 0 );
1992 vc_clut8 = NULL;
1993 disableConsoleOutput = TRUE;
1994 break;
1995 }
1996 }