]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/AT386/video_console.c
xnu-344.tar.gz
[apple/xnu.git] / osfmk / i386 / AT386 / video_console.c
CommitLineData
1c79356b
A
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
115enum 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
130static struct vc_info vinfo;
131#define IS_TEXT_MODE (vinfo.v_type == TEXT_MODE)
132
133/* Calculated in vccninit(): */
134static int vc_wrap_mode = 1, vc_relative_origin = 0;
135static int vc_charset_select = 0, vc_save_charset_s = 0;
136static int vc_charset[2] = { 0, 0 };
137static int vc_charset_save[2] = { 0, 0 };
138
139/* VT100 state: */
140#define MAXPARS 16
141static int x = 0, y = 0, savex, savey;
142static int par[MAXPARS], numpars, hanging_cursor, attr, saveattr;
143
144/* VT100 tab stops & scroll region */
145static char tab_stops[255];
146static int scrreg_top, scrreg_bottom;
147
148/* Misc */
149void vc_flush_forward_buffer(void);
150void vc_store_char(unsigned char);
151
152/*
153 * For the color support (Michel Pollet)
154 */
155unsigned 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
159unsigned long vc_color_depth_masks[4] =
160 { 0x000000FF, 0x00007FFF, 0x00FFFFFF };
161
162unsigned 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
174unsigned long vc_color_mask = 0;
175unsigned long vc_color_fore = 0;
176unsigned long vc_color_back = 0;
177int 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
195static unsigned char vc_forward_buffer[VC_MAX_FORWARD_SIZE];
196static long vc_forward_buffer_size = 0;
197decl_simple_lock_data(,vc_forward_lock)
198
199/* Set to 1 by initialize_screen() */
200static int vc_initialized = 0;
201
202/* Function pointers initialized via initialize_screen() */
203static 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)
221unsigned char renderedFont[REN_MAX_SIZE];
222
223/* Rendered Font Size */
224unsigned long vc_rendered_font_size = REN_MAX_SIZE;
225long vc_rendered_error = 0;
226
227/* If the one bit table was reversed */
228short vc_one_bit_reversed = 0;
229
230/* Size of a character in the table (bytes) */
231int 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
245static 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
260static 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
354static 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
390static 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
425static 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
461static 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}
509static 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}
553static 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 */
601static 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 */
9bccf70c 629#if 1 /*VC_BINARY_REVERSE*/
1c79356b
A
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
665static void
666scrollup(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
714static void
715scrolldown(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
766static void
767clear_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
800static void
801clear_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
841static void
842reset_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
852static void
853vt100_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
868static void
869putc_normal(unsigned char ch)
870{
871 switch (ch) {
872 case '\a': /* Beep */
873 {
0b4e3aa0 874 if ( FALSE && !IS_TEXT_MODE ) {
1c79356b
A
875 /*
876 * No sound hardware, invert the screen twice instead
877 */
878 unsigned long *ptr;
879 int i, j;
880 /* XOR the screen twice */
881 for (i = 0; i < 2 ; i++) {
882 /* For each row, xor the scanbytes */
883 for (ptr = (unsigned long*)vinfo.v_baseaddr;
884 ptr < (unsigned long*)(vinfo.v_baseaddr +
885 (vinfo.v_height * vinfo.v_rowbytes));
886 ptr += (vinfo.v_rowbytes /
887 sizeof (unsigned long*)))
888 for (j = 0;
889 j < vinfo.v_rowscanbytes /
890 sizeof (unsigned long*);
891 j++)
892 *(ptr+j) =~*(ptr+j);
893 }
894 }
895 }
896 break;
897
898 case 127: /* Delete */
899 case '\b': /* Backspace */
900 if (hanging_cursor) {
901 hanging_cursor = 0;
902 } else
903 if (x > 0) {
904 x--;
905 }
906 break;
907 case '\t': /* Tab */
908 while (x < vinfo.v_columns && !tab_stops[++x]);
909 if (x >= vinfo.v_columns)
910 x = vinfo.v_columns-1;
911 break;
912 case 0x0b:
913 case 0x0c:
914 case '\n': /* Line feed */
915 if (y >= scrreg_bottom -1 ) {
916 vc_ops.scrollup(1);
917 y = scrreg_bottom - 1;
918 } else {
919 y++;
920 }
921 /*break; Pass thru */
922 case '\r': /* Carriage return */
923 x = 0;
924 hanging_cursor = 0;
925 break;
926 case 0x0e: /* Select G1 charset (Control-N) */
927 vc_charset_select = 1;
928 break;
929 case 0x0f: /* Select G0 charset (Control-O) */
930 vc_charset_select = 0;
931 break;
932 case 0x18 : /* CAN : cancel */
933 case 0x1A : /* like cancel */
934 /* well, i do nothing here, may be later */
935 break;
936 case '\033': /* Escape */
937 vt100state = ESesc;
938 hanging_cursor = 0;
939 break;
940 default:
941 if (ch >= ' ') {
942 if (hanging_cursor) {
943 x = 0;
944 if (y >= scrreg_bottom -1 ) {
945 vc_ops.scrollup(1);
946 y = scrreg_bottom - 1;
947 } else {
948 y++;
949 }
950 hanging_cursor = 0;
951 }
952 vc_ops.paintchar((ch >= 0x60 && ch <= 0x7f) ? ch + vc_charset[vc_charset_select]
953 : ch, x, y, attr);
954 if (x == vinfo.v_columns - 1) {
955 hanging_cursor = vc_wrap_mode;
956 } else {
957 x++;
958 }
959 }
960 break;
961 }
962
963}
964
965static void
966putc_esc(unsigned char ch)
967{
968 vt100state = ESnormal;
969
970 switch (ch) {
971 case '[':
972 vt100state = ESsquare;
973 break;
974 case 'c': /* Reset terminal */
975 vt100_reset();
976 vc_ops.clear_screen(x, y, 2);
977 x = y = 0;
978 break;
979 case 'D': /* Line feed */
980 case 'E':
981 if (y >= scrreg_bottom -1) {
982 vc_ops.scrollup(1);
983 y = scrreg_bottom - 1;
984 } else {
985 y++;
986 }
987 if (ch == 'E') x = 0;
988 break;
989 case 'H': /* Set tab stop */
990 tab_stops[x] = 1;
991 break;
992 case 'M': /* Cursor up */
993 if (y <= scrreg_top) {
994 vc_ops.scrolldown(1);
995 y = scrreg_top;
996 } else {
997 y--;
998 }
999 break;
1000 case '>':
1001 vt100_reset();
1002 break;
1003 case '7': /* Save cursor */
1004 savex = x;
1005 savey = y;
1006 saveattr = attr;
1007 vc_save_charset_s = vc_charset_select;
1008 vc_charset_save[0] = vc_charset[0];
1009 vc_charset_save[1] = vc_charset[1];
1010 break;
1011 case '8': /* Restore cursor */
1012 x = savex;
1013 y = savey;
1014 attr = saveattr;
1015 vc_charset_select = vc_save_charset_s;
1016 vc_charset[0] = vc_charset_save[0];
1017 vc_charset[1] = vc_charset_save[1];
1018 break;
1019 case 'Z': /* return terminal ID */
1020 break;
1021 case '#': /* change characters height */
1022 vt100state = EScharsize;
1023 break;
1024 case '(':
1025 vt100state = ESsetG0;
1026 break;
1027 case ')': /* character set sequence */
1028 vt100state = ESsetG1;
1029 break;
1030 case '=':
1031 break;
1032 default:
1033 /* Rest not supported */
1034 break;
1035 }
1036
1037}
1038
1039static void
1040putc_askcmd(unsigned char ch)
1041{
1042 if (ch >= '0' && ch <= '9') {
1043 par[numpars] = (10*par[numpars]) + (ch-'0');
1044 return;
1045 }
1046 vt100state = ESnormal;
1047
1048 switch (par[0]) {
1049 case 6:
1050 vc_relative_origin = ch == 'h';
1051 break;
1052 case 7: /* wrap around mode h=1, l=0*/
1053 vc_wrap_mode = ch == 'h';
1054 break;
1055 default:
1056 break;
1057 }
1058
1059}
1060
1061static void
1062putc_charsizecmd(unsigned char ch)
1063{
1064 vt100state = ESnormal;
1065
1066 switch (ch) {
1067 case '3' :
1068 case '4' :
1069 case '5' :
1070 case '6' :
1071 break;
1072 case '8' : /* fill 'E's */
1073 {
1074 int xx, yy;
1075 for (yy = 0; yy < vinfo.v_rows; yy++)
1076 for (xx = 0; xx < vinfo.v_columns; xx++)
1077 vc_ops.paintchar('E', xx, yy, ATTR_NONE);
1078 }
1079 break;
1080 }
1081
1082}
1083
1084static void
1085putc_charsetcmd(int charset, unsigned char ch)
1086{
1087 vt100state = ESnormal;
1088
1089 switch (ch) {
1090 case 'A' :
1091 case 'B' :
1092 default:
1093 vc_charset[charset] = 0;
1094 break;
1095 case '0' : /* Graphic characters */
1096 case '2' :
1097 vc_charset[charset] = 0x21;
1098 break;
1099 }
1100
1101}
1102
1103static void
1104putc_gotpars(unsigned char ch)
1105{
1106 int i;
1107
1108 if (ch < ' ') {
1109 /* special case for vttest for handling cursor
1110 movement in escape sequences */
1111 putc_normal(ch);
1112 vt100state = ESgotpars;
1113 return;
1114 }
1115 vt100state = ESnormal;
1116 switch (ch) {
1117 case 'A': /* Up */
1118 y -= par[0] ? par[0] : 1;
1119 if (y < scrreg_top)
1120 y = scrreg_top;
1121 break;
1122 case 'B': /* Down */
1123 y += par[0] ? par[0] : 1;
1124 if (y >= scrreg_bottom)
1125 y = scrreg_bottom - 1;
1126 break;
1127 case 'C': /* Right */
1128 x += par[0] ? par[0] : 1;
1129 if (x >= vinfo.v_columns)
1130 x = vinfo.v_columns-1;
1131 break;
1132 case 'D': /* Left */
1133 x -= par[0] ? par[0] : 1;
1134 if (x < 0)
1135 x = 0;
1136 break;
1137 case 'H': /* Set cursor position */
1138 case 'f':
1139 x = par[1] ? par[1] - 1 : 0;
1140 y = par[0] ? par[0] - 1 : 0;
1141 if (vc_relative_origin)
1142 y += scrreg_top;
1143 hanging_cursor = 0;
1144 break;
1145 case 'X': /* clear p1 characters */
1146 if (numpars) {
1147 int i;
1148 for (i = x; i < x + par[0]; i++)
1149 vc_ops.paintchar(' ', i, y, ATTR_NONE);
1150 }
1151 break;
1152 case 'J': /* Clear part of screen */
1153 vc_ops.clear_screen(x, y, par[0]);
1154 break;
1155 case 'K': /* Clear part of line */
1156 clear_line(par[0]);
1157 break;
1158 case 'g': /* tab stops */
1159 switch (par[0]) {
1160 case 1:
1161 case 2: /* reset tab stops */
1162 /* reset_tabs(); */
1163 break;
1164 case 3: /* Clear every tabs */
1165 {
1166 int i;
1167
1168 for (i = 0; i <= vinfo.v_columns; i++)
1169 tab_stops[i] = 0;
1170 }
1171 break;
1172 case 0:
1173 tab_stops[x] = 0;
1174 break;
1175 }
1176 break;
1177 case 'm': /* Set attribute */
1178 for (i = 0; i < numpars; i++) {
1179 switch (par[i]) {
1180 case 0:
1181 attr = ATTR_NONE;
1182 vc_color_set(VC_RESET_BACKGROUND);
1183 vc_color_set(VC_RESET_FOREGROUND);
1184 break;
1185 case 1:
1186 attr |= ATTR_BOLD;
1187 break;
1188 case 4:
1189 attr |= ATTR_UNDER;
1190 break;
1191 case 7:
1192 attr |= ATTR_REVERSE;
1193 break;
1194 case 22:
1195 attr &= ~ATTR_BOLD;
1196 break;
1197 case 24:
1198 attr &= ~ATTR_UNDER;
1199 break;
1200 case 27:
1201 attr &= ~ATTR_REVERSE;
1202 break;
1203 case 5:
1204 case 25: /* blink/no blink */
1205 break;
1206 default:
1207 vc_color_set(par[i]);
1208 break;
1209 }
1210 }
1211 break;
1212 case 'r': /* Set scroll region */
1213 x = y = 0;
1214 /* ensure top < bottom, and both within limits */
1215 if ((numpars > 0) && (par[0] < vinfo.v_rows)) {
1216 scrreg_top = par[0] ? par[0] - 1 : 0;
1217 if (scrreg_top < 0)
1218 scrreg_top = 0;
1219 } else {
1220 scrreg_top = 0;
1221 }
1222 if ((numpars > 1) && (par[1] <= vinfo.v_rows) && (par[1] > par[0])) {
1223 scrreg_bottom = par[1];
1224 if (scrreg_bottom > vinfo.v_rows)
1225 scrreg_bottom = vinfo.v_rows;
1226 } else {
1227 scrreg_bottom = vinfo.v_rows;
1228 }
1229 if (vc_relative_origin)
1230 y = scrreg_top;
1231 break;
1232 }
1233
1234}
1235
1236static void
1237putc_getpars(unsigned char ch)
1238{
1239 if (ch == '?') {
1240 vt100state = ESask;
1241 return;
1242 }
1243 if (ch == '[') {
1244 vt100state = ESnormal;
1245 /* Not supported */
1246 return;
1247 }
1248 if (ch == ';' && numpars < MAXPARS - 1) {
1249 numpars++;
1250 } else
1251 if (ch >= '0' && ch <= '9') {
1252 par[numpars] *= 10;
1253 par[numpars] += ch - '0';
1254 } else {
1255 numpars++;
1256 vt100state = ESgotpars;
1257 putc_gotpars(ch);
1258 }
1259}
1260
1261static void
1262putc_square(unsigned char ch)
1263{
1264 int i;
1265
1266 for (i = 0; i < MAXPARS; i++) {
1267 par[i] = 0;
1268 }
1269
1270 numpars = 0;
1271 vt100state = ESgetpars;
1272
1273 putc_getpars(ch);
1274
1275}
1276
1277void
1278vc_putchar(char ch)
1279{
1280 if (!ch) {
1281 return; /* ignore null characters */
1282 }
1283
1284 switch (vt100state) {
1285 default:vt100state = ESnormal; /* FALLTHROUGH */
1286 case ESnormal:
1287 putc_normal(ch);
1288 break;
1289 case ESesc:
1290 putc_esc(ch);
1291 break;
1292 case ESsquare:
1293 putc_square(ch);
1294 break;
1295 case ESgetpars:
1296 putc_getpars(ch);
1297 break;
1298 case ESgotpars:
1299 putc_gotpars(ch);
1300 break;
1301 case ESask:
1302 putc_askcmd(ch);
1303 break;
1304 case EScharsize:
1305 putc_charsizecmd(ch);
1306 break;
1307 case ESsetG0:
1308 putc_charsetcmd(0, ch);
1309 break;
1310 case ESsetG1:
1311 putc_charsetcmd(1, ch);
1312 break;
1313 }
1314
1315 if (x >= vinfo.v_columns) {
1316 x = vinfo.v_columns - 1;
1317 }
1318 if (x < 0) {
1319 x = 0;
1320 }
1321 if (y >= vinfo.v_rows) {
1322 y = vinfo.v_rows - 1;
1323 }
1324 if (y < 0) {
1325 y = 0;
1326 }
1327
1328}
1329
1330/*
1331 * Actually draws the buffer, handle the jump scroll
1332 */
1333void vc_flush_forward_buffer(void)
1334{
1335 if (vc_forward_buffer_size) {
1336 int start = 0;
1337 vc_ops.hide_cursor(x, y);
1338 do {
1339 int i;
1340 int plaintext = 1;
1341 int drawlen = start;
1342 int jump = 0;
1343 int param = 0, changebackground = 0;
1344 enum vt100state_e vtState = vt100state;
1345 /*
1346 * In simple words, here we're pre-parsing the text to look for
1347 * + Newlines, for computing jump scroll
1348 * + /\033\[[0-9;]*]m/ to continue on
1349 * any other sequence will stop. We don't want to have cursor
1350 * movement escape sequences while we're trying to pre-scroll
1351 * the screen.
1352 * We have to be extra carefull about the sequences that changes
1353 * the background color to prevent scrolling in those
1354 * particular cases.
1355 * That parsing was added to speed up 'man' and 'color-ls' a
1356 * zillion time (at least). It's worth it, trust me.
1357 * (mail Nick Stephen for a True Performance Graph)
1358 * Michel Pollet
1359 */
1360 for (i = start; i < vc_forward_buffer_size && plaintext; i++) {
1361 drawlen++;
1362 switch (vtState) {
1363 case ESnormal:
1364 switch (vc_forward_buffer[i]) {
1365 case '\033':
1366 vtState = ESesc;
1367 break;
1368 case '\n':
1369 jump++;
1370 break;
1371 }
1372 break;
1373 case ESesc:
1374 switch (vc_forward_buffer[i]) {
1375 case '[':
1376 vtState = ESgetpars;
1377 param = 0;
1378 changebackground = 0;
1379 break;
1380 default:
1381 plaintext = 0;
1382 break;
1383 }
1384 break;
1385 case ESgetpars:
1386 if ((vc_forward_buffer[i] >= '0' &&
1387 vc_forward_buffer[i] <= '9') ||
1388 vc_forward_buffer[i] == ';') {
1389 if (vc_forward_buffer[i] >= '0' &&
1390 vc_forward_buffer[i] <= '9')
1391 param = (param*10)+(vc_forward_buffer[i]-'0');
1392 else {
1393 if (param >= 40 && param <= 47)
1394 changebackground = 1;
1395 if (!vc_normal_background &&
1396 !param)
1397 changebackground = 1;
1398 param = 0;
1399 }
1400 break; /* continue on */
1401 }
1402 vtState = ESgotpars;
1403 /* fall */
1404 case ESgotpars:
1405 switch (vc_forward_buffer[i]) {
1406 case 'm':
1407 vtState = ESnormal;
1408 if (param >= 40 && param <= 47)
1409 changebackground = 1;
1410 if (!vc_normal_background &&
1411 !param)
1412 changebackground = 1;
1413 if (changebackground) {
1414 plaintext = 0;
1415 jump = 0;
1416 /* REALLY don't jump */
1417 }
1418 /* Yup ! we've got it */
1419 break;
1420 default:
1421 plaintext = 0;
1422 break;
1423 }
1424 break;
1425 default:
1426 plaintext = 0;
1427 break;
1428 }
1429
1430 }
1431
1432 /*
1433 * Then we look if it would be appropriate to forward jump
1434 * the screen before drawing
1435 */
1436 if (jump && (scrreg_bottom - scrreg_top) > 2) {
1437 jump -= scrreg_bottom - y - 1;
1438 if (jump > 0 ) {
1439 if (jump >= scrreg_bottom - scrreg_top)
1440 jump = scrreg_bottom - scrreg_top -1;
1441 y -= jump;
1442 vc_ops.scrollup(jump);
1443 }
1444 }
1445 /*
1446 * and we draw what we've found to the parser
1447 */
1448 for (i = start; i < drawlen; i++)
1449 vc_putchar(vc_forward_buffer[start++]);
1450 /*
1451 * Continue sending characters to the parser until we're sure we're
1452 * back on normal characters.
1453 */
1454 for (i = start; i < vc_forward_buffer_size &&
1455 vt100state != ESnormal ; i++)
1456 vc_putchar(vc_forward_buffer[start++]);
1457 /* Then loop again if there still things to draw */
1458 } while (start < vc_forward_buffer_size);
1459 vc_forward_buffer_size = 0;
1460 vc_ops.show_cursor(x, y);
1461 }
1462}
1463
1464int
1465vcputc(int l, int u, int c)
1466{
1467 if ( vc_initialized )
1468 {
1469 vc_store_char(c);
1470 vc_flush_forward_buffer();
1471 }
1472 return 0;
1473}
1474
1475/*
1476 * Immediate character display.. kernel printf uses this. Make sure
1477 * pre-clock printfs get flushed and that panics get fully displayed.
1478 */
1479
1480void cnputc(char ch)
1481{
1482 vcputc(0, 0, ch);
1483}
1484
1485/*
1486 * Store characters to be drawn 'later', handle overflows
1487 */
1488
1489void
1490vc_store_char(unsigned char c)
1491{
1492
1493 /* Either we're really buffering stuff or we're not yet because
1494 * the probe hasn't been done. If we're not, then we can only
1495 * ever have a maximum of one character in the buffer waiting to
1496 * be flushed
1497 */
1498
1499 vc_forward_buffer[vc_forward_buffer_size++] = (unsigned char)c;
1500
1501 switch (vc_forward_buffer_size) {
1502 case 1:
1503 /* If we're adding the first character to the buffer,
1504 * start the timer, otherwise it is already running.
1505 */
1506 break;
1507 case VC_MAX_FORWARD_SIZE:
1508 vc_flush_forward_buffer();
1509 break;
1510 default:
1511 /*
1512 * the character will be flushed on timeout
1513 */
1514 break;
1515 }
1516}
1517
1518static void
1519vc_initialize(struct vc_info * vinfo_p)
1520{
1521 vinfo.v_rows = vinfo.v_height / CHARHEIGHT;
1522 vinfo.v_columns = vinfo.v_width / CHARWIDTH;
1523
1524 if (vinfo.v_depth >= 8) {
1525 vinfo.v_rowscanbytes = (vinfo.v_depth / 8) * vinfo.v_width;
1526 } else {
1527 vinfo.v_rowscanbytes = vinfo.v_width / (8 / vinfo.v_depth);
1528 }
1529
1530 vc_render_font(1, vinfo.v_depth);
1531 vc_color_mask = vc_color_depth_masks[vc_color_index_table[vinfo.v_depth]];
1532 vt100_reset();
1533 switch (vinfo.v_depth) {
1534 default:
1535 case 1:
1536 vc_ops.paintchar = vc_paint_char1;
1537 break;
1538 case 2:
1539 vc_ops.paintchar = vc_paint_char2;
1540 break;
1541 case 4:
1542 vc_ops.paintchar = vc_paint_char4;
1543 break;
1544 case 8:
1545 vc_ops.paintchar = vc_paint_char8c;
1546 break;
1547 case 16:
1548 vc_ops.paintchar = vc_paint_char16c;
1549 break;
1550 case 32:
1551 vc_ops.paintchar = vc_paint_char32c;
1552 break;
1553 }
1554}
1555
1556void
1557vcattach(void)
1558{
1559 if (vinfo.v_depth >= 8)
1560 printf("\033[31mC\033[32mO\033[33mL\033[34mO\033[35mR\033[0m ");
1561 printf("video console at 0x%lx (%ldx%ldx%ld)\n", vinfo.v_baseaddr,
1562 vinfo.v_width, vinfo.v_height, vinfo.v_depth);
1563
1564#if 0 // XXX - FIXME
1565 /*
1566 * Added for the buffering and jump scrolling
1567 */
1568 /* Init our lock */
1569 simple_lock_init(&vc_forward_lock, ETAP_IO_TTY);
1570
1571 vc_forward_buffer_enabled = 1;
1572#else // FIXME TOO!!!
1573 /* Init our lock */
1574 simple_lock_init(&vc_forward_lock, ETAP_IO_TTY);
1575#endif
1576}
1577
1578
1579struct vc_progress_element {
1580 unsigned int version;
1581 unsigned int flags;
1582 unsigned int time;
1583 unsigned char count;
1584 unsigned char res[3];
1585 int width;
1586 int height;
1587 int dx;
1588 int dy;
1589 int transparent;
1590 unsigned int res2[3];
1591 unsigned char data[0];
1592};
1593typedef struct vc_progress_element vc_progress_element;
1594
1595static vc_progress_element * vc_progress;
9bccf70c
A
1596static const unsigned char * vc_progress_data;
1597static const unsigned char * vc_progress_alpha;
1c79356b 1598static boolean_t vc_progress_enable;
9bccf70c
A
1599static const unsigned char * vc_clut;
1600static const unsigned char * vc_clut8;
1c79356b
A
1601static unsigned int vc_progress_tick;
1602static boolean_t vc_graphics_mode;
1603static boolean_t vc_acquired;
1604static boolean_t vc_need_clear;
9bccf70c
A
1605static boolean_t vc_needsave;
1606static vm_address_t vc_saveunder;
1607static vm_size_t vc_saveunder_len;
1c79356b
A
1608
1609void vc_blit_rect_8c( int x, int y,
1610 int width, int height,
9bccf70c
A
1611 const unsigned char * dataPtr, const unsigned char * alphaPtr,
1612 unsigned char * backPtr, boolean_t save )
1c79356b
A
1613{
1614 volatile unsigned char * dst;
1615 int line, col;
1616 unsigned char data;
1617
1618 dst = (unsigned char *)(vinfo.v_baseaddr +
1619 (y * vinfo.v_rowbytes) +
1620 (x));
1621
1c79356b 1622 dst = (unsigned char *)(vinfo.v_baseaddr +
9bccf70c
A
1623 (y * vinfo.v_rowbytes) +
1624 (x));
1c79356b
A
1625
1626 for( line = 0; line < height; line++) {
9bccf70c
A
1627 for( col = 0; col < width; col++)
1628 *(dst + col) = *dataPtr++;
1c79356b
A
1629 dst = (volatile unsigned char *) (((int)dst) + vinfo.v_rowbytes);
1630 }
1631}
1632
1633void vc_blit_rect_16( int x, int y,
1634 int width, int height,
9bccf70c
A
1635 const unsigned char * dataPtr, const unsigned char * alphaPtr,
1636 unsigned short * backPtr, boolean_t save )
1c79356b
A
1637{
1638 volatile unsigned short * dst;
1639 int line, col;
9bccf70c 1640 unsigned int data, index, alpha, back;
1c79356b
A
1641
1642 dst = (volatile unsigned short *)(vinfo.v_baseaddr +
1643 (y * vinfo.v_rowbytes) +
1644 (x * 2));
1645
1646 for( line = 0; line < height; line++) {
1647 for( col = 0; col < width; col++) {
9bccf70c
A
1648 index = *dataPtr++;
1649 index *= 3;
1650
1651 if( alphaPtr && backPtr && (alpha = *alphaPtr++)) {
1652
1653 data = 0;
1654 if( vc_clut[index + 0] > alpha)
1655 data |= (((vc_clut[index + 0] - alpha) & 0xf8) << 7);
1656 if( vc_clut[index + 1] > alpha)
1657 data |= (((vc_clut[index + 1] - alpha) & 0xf8) << 2);
1658 if( vc_clut[index + 2] > alpha)
1659 data |= (((vc_clut[index + 2] - alpha) & 0xf8) >> 3);
1660
1661 if( save) {
1662 back = *(dst + col);
1663 alpha >>= 3;
1664 back = (((((back & 0x7c1f) * alpha) + 0x7c1f) >> 5) & 0x7c1f)
1665 | (((((back & 0x03e0) * alpha) + 0x03e0) >> 5) & 0x03e0);
1666 *backPtr++ = back;
1667 } else
1668 back = *backPtr++;
1669
1670 data += back;
1671
1672 } else
1673 data = ( (0xf8 & (vc_clut[index + 0])) << 7)
1674 | ( (0xf8 & (vc_clut[index + 1])) << 2)
1675 | ( (0xf8 & (vc_clut[index + 2])) >> 3);
1676
1677 *(dst + col) = data;
1c79356b
A
1678 }
1679 dst = (volatile unsigned short *) (((int)dst) + vinfo.v_rowbytes);
1680 }
1681}
1682
1683void vc_blit_rect_32( unsigned int x, unsigned int y,
1684 unsigned int width, unsigned int height,
9bccf70c
A
1685 const unsigned char * dataPtr, const unsigned char * alphaPtr,
1686 unsigned int * backPtr, boolean_t save )
1c79356b
A
1687{
1688 volatile unsigned int * dst;
1689 int line, col;
9bccf70c 1690 unsigned int data, index, alpha, back;
1c79356b
A
1691
1692 dst = (volatile unsigned int *) (vinfo.v_baseaddr +
1693 (y * vinfo.v_rowbytes) +
1694 (x * 4));
1695
1696 for( line = 0; line < height; line++) {
1697 for( col = 0; col < width; col++) {
9bccf70c
A
1698 index = *dataPtr++;
1699 index *= 3;
1700 if( alphaPtr && backPtr && (alpha = *alphaPtr++)) {
1701
1702 data = 0;
1703 if( vc_clut[index + 0] > alpha)
1704 data |= ((vc_clut[index + 0] - alpha) << 16);
1705 if( vc_clut[index + 1] > alpha)
1706 data |= ((vc_clut[index + 1] - alpha) << 8);
1707 if( vc_clut[index + 2] > alpha)
1708 data |= ((vc_clut[index + 2] - alpha));
1709
1710 if( save) {
1711 back = *(dst + col);
1712 back = (((((back & 0x00ff00ff) * alpha) + 0x00ff00ff) >> 8) & 0x00ff00ff)
1713 | (((((back & 0x0000ff00) * alpha) + 0x0000ff00) >> 8) & 0x0000ff00);
1714 *backPtr++ = back;
1715 } else
1716 back = *backPtr++;
1717
1718 data += back;
1719
1720 } else
1721 data = (vc_clut[index + 0] << 16)
1722 | (vc_clut[index + 1] << 8)
1723 | (vc_clut[index + 2]);
1724
1725 *(dst + col) = data;
1c79356b
A
1726 }
1727 dst = (volatile unsigned int *) (((int)dst) + vinfo.v_rowbytes);
1728 }
1729}
1730
9bccf70c
A
1731void vc_blit_rect( unsigned int x, unsigned int y,
1732 unsigned int width, unsigned int height,
1733 const unsigned char * dataPtr, const unsigned char * alphaPtr,
1734 vm_address_t backBuffer, boolean_t save )
1c79356b 1735{
9bccf70c
A
1736 if(!vinfo.v_baseaddr)
1737 return;
1738
1c79356b
A
1739 switch( vinfo.v_depth) {
1740 case 8:
9bccf70c
A
1741 if( vc_clut8 == vc_clut)
1742 vc_blit_rect_8c( x, y, width, height, dataPtr, alphaPtr, (unsigned char *) backBuffer, save );
1c79356b
A
1743 break;
1744 case 16:
9bccf70c 1745 vc_blit_rect_16( x, y, width, height, dataPtr, alphaPtr, (unsigned short *) backBuffer, save );
1c79356b
A
1746 break;
1747 case 32:
9bccf70c 1748 vc_blit_rect_32( x, y, width, height, dataPtr, alphaPtr, (unsigned int *) backBuffer, save );
1c79356b
A
1749 break;
1750 }
1751}
1752
1753void vc_progress_task( void * arg )
1754{
1755 spl_t s;
1756 int count = (int) arg;
1757 int x, y, width, height;
9bccf70c 1758 const unsigned char * data;
1c79356b
A
1759
1760 s = splhigh();
1761 simple_lock(&vc_forward_lock);
1762
1763 if( vc_progress_enable) {
9bccf70c 1764
1c79356b
A
1765 count++;
1766 if( count >= vc_progress->count)
1767 count = 0;
1768
1769 width = vc_progress->width;
1770 height = vc_progress->height;
1771 x = vc_progress->dx;
1772 y = vc_progress->dy;
1773 data = vc_progress_data;
1774 data += count * width * height;
1775 if( 1 & vc_progress->flags) {
9bccf70c
A
1776 x += ((vinfo.v_width - width) / 2);
1777 y += ((vinfo.v_height - height) / 2);
1c79356b
A
1778 }
1779 vc_blit_rect( x, y, width, height,
9bccf70c
A
1780 data, vc_progress_alpha, vc_saveunder, vc_needsave );
1781 vc_needsave = FALSE;
1c79356b
A
1782
1783 timeout( vc_progress_task, (void *) count,
1784 vc_progress_tick );
1785 }
1786 simple_unlock(&vc_forward_lock);
1787 splx(s);
1788}
1789
1790void vc_display_icon( vc_progress_element * desc,
9bccf70c 1791 const unsigned char * data )
1c79356b
A
1792{
1793 int x, y, width, height;
1794
1795 if( vc_acquired && vc_graphics_mode && vc_clut) {
1796
1797 width = desc->width;
1798 height = desc->height;
1799 x = desc->dx;
1800 y = desc->dy;
1801 if( 1 & desc->flags) {
9bccf70c
A
1802 x += ((vinfo.v_width - width) / 2);
1803 y += ((vinfo.v_height - height) / 2);
1c79356b 1804 }
9bccf70c 1805 vc_blit_rect( x, y, width, height, data, NULL, (vm_address_t) NULL, FALSE );
1c79356b
A
1806 }
1807}
1808
1809boolean_t
9bccf70c 1810vc_progress_set( boolean_t enable, unsigned int initial_tick )
1c79356b
A
1811{
1812 spl_t s;
9bccf70c
A
1813 vm_address_t saveBuf = 0;
1814 vm_size_t saveLen = 0;
1c79356b
A
1815
1816 if( !vc_progress)
1817 return( FALSE );
1818
9bccf70c
A
1819 if( enable) {
1820 saveLen = vc_progress->width * vc_progress->height * vinfo.v_depth / 8;
1821 saveBuf = kalloc( saveLen );
1822 }
1823
1c79356b
A
1824 s = splhigh();
1825 simple_lock(&vc_forward_lock);
1826
1827 if( vc_progress_enable != enable) {
1828 vc_progress_enable = enable;
9bccf70c
A
1829 if( enable) {
1830 vc_needsave = TRUE;
1831 vc_saveunder = saveBuf;
1832 vc_saveunder_len = saveLen;
1833 saveBuf = 0;
1834 saveLen = 0;
1c79356b 1835 timeout(vc_progress_task, (void *) 0,
9bccf70c
A
1836 initial_tick );
1837 }
1838 else {
1839 if( vc_saveunder) {
1840 saveBuf = vc_saveunder;
1841 saveLen = vc_saveunder_len;
1842 vc_saveunder = 0;
1843 vc_saveunder_len = 0;
1844 }
1c79356b 1845 untimeout( vc_progress_task, (void *) 0 );
9bccf70c 1846 }
1c79356b
A
1847 }
1848
1849 simple_unlock(&vc_forward_lock);
1850 splx(s);
1851
9bccf70c
A
1852 if( saveBuf)
1853 kfree( saveBuf, saveLen );
1854
1c79356b
A
1855 return( TRUE );
1856}
1857
1858
1859boolean_t
1860vc_progress_initialize( vc_progress_element * desc,
9bccf70c
A
1861 const unsigned char * data,
1862 const unsigned char * clut )
1c79356b
A
1863{
1864 if( (!clut) || (!desc) || (!data))
1865 return( FALSE );
1866 vc_clut = clut;
9bccf70c 1867 vc_clut8 = clut;
1c79356b
A
1868
1869 vc_progress = desc;
1870 vc_progress_data = data;
9bccf70c
A
1871 if( 2 & vc_progress->flags)
1872 vc_progress_alpha = vc_progress_data
1873 + vc_progress->count * vc_progress->width * vc_progress->height;
1874 else
1875 vc_progress_alpha = NULL;
1c79356b
A
1876 vc_progress_tick = vc_progress->time * hz / 1000;
1877
1878 return( TRUE );
1879}
1880
1881extern int disableConsoleOutput;
1882
1883void vc_clear_screen( void )
1884{
1885 vc_ops.hide_cursor(x, y);
1886 vt100_reset();
1887 x = y = 0;
1888 vc_ops.clear_screen(x, y, 2);
1889 vc_ops.show_cursor(x, y);
1890};
1891
1892void
1893initialize_screen(Boot_Video * boot_vinfo, int op)
1894{
1895 if ( boot_vinfo )
1896 {
1897 vinfo.v_width = boot_vinfo->v_width;
1898 vinfo.v_height = boot_vinfo->v_height;
1899 vinfo.v_depth = boot_vinfo->v_depth;
1900 vinfo.v_rowbytes = boot_vinfo->v_rowBytes;
1901 vinfo.v_baseaddr = boot_vinfo->v_baseAddr;
1902 vinfo.v_type = boot_vinfo->v_display;
1903
1904 if ( IS_TEXT_MODE )
1905 {
1906 // Text mode setup by the booter.
1907
1908 vc_ops.initialize = tc_initialize;
1909 vc_ops.paintchar = tc_putchar;
1910 vc_ops.scrolldown = tc_scrolldown;
1911 vc_ops.scrollup = tc_scrollup;
1912 vc_ops.clear_screen = tc_clear_screen;
1913 vc_ops.hide_cursor = tc_hide_cursor;
1914 vc_ops.show_cursor = tc_show_cursor;
1915 vc_ops.update_color = tc_update_color;
1916 }
1917 else
1918 {
1919 // Graphics mode setup by the booter.
1920
1921 vc_ops.initialize = vc_initialize;
1922 vc_ops.paintchar = 0;
1923 vc_ops.scrolldown = scrolldown;
1924 vc_ops.scrollup = scrollup;
1925 vc_ops.clear_screen = clear_screen;
1926 vc_ops.hide_cursor = reversecursor;
1927 vc_ops.show_cursor = reversecursor;
1928 vc_ops.update_color = 0;
1929 }
1930
1931 vc_ops.initialize(&vinfo);
1932
1933 // vc_clear_screen();
1934
1935 vc_initialized = 1;
1936 }
1937
1938 switch ( op ) {
1939
1940 case kPEGraphicsMode:
1941 vc_graphics_mode = TRUE;
1942 disableConsoleOutput = TRUE;
1943 vc_acquired = TRUE;
1944 break;
1945
1946 case kPETextMode:
1947 vc_graphics_mode = FALSE;
1948 disableConsoleOutput = FALSE;
1949 vc_acquired = TRUE;
1950 vc_clear_screen();
1951 break;
1952
1953 case kPETextScreen:
9bccf70c 1954 vc_progress_set( FALSE, 0 );
1c79356b
A
1955 disableConsoleOutput = FALSE;
1956 if( vc_need_clear) {
1957 vc_need_clear = FALSE;
1958 vc_clear_screen();
1959 }
1960 break;
1961
1962 case kPEEnableScreen:
1963 if ( vc_acquired) {
1964 if( vc_graphics_mode)
9bccf70c 1965 vc_progress_set( TRUE, vc_progress_tick );
1c79356b
A
1966 else
1967 vc_clear_screen();
1968 }
1969 break;
1970
1971 case kPEDisableScreen:
9bccf70c 1972 vc_progress_set( FALSE, 0 );
1c79356b
A
1973 break;
1974
1975 case kPEAcquireScreen:
1976 vc_need_clear = (FALSE == vc_acquired);
1977 vc_acquired = TRUE;
9bccf70c 1978 vc_progress_set( vc_graphics_mode, vc_need_clear ? 2 * hz : 0 );
1c79356b
A
1979 disableConsoleOutput = vc_graphics_mode;
1980 if( vc_need_clear && !vc_graphics_mode) {
1981 vc_need_clear = FALSE;
1982 vc_clear_screen();
1983 }
1984 break;
1985
1986 case kPEReleaseScreen:
1987 vc_acquired = FALSE;
9bccf70c
A
1988 vc_progress_set( FALSE, 0 );
1989 vc_clut8 = NULL;
1c79356b
A
1990 disableConsoleOutput = TRUE;
1991 break;
1992 }
1993}