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