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