1 /* $NetBSD: vga.c,v 1.5 2006/04/10 18:40:06 garbled Exp $ */
4 * Copyright (C) 1995-1997 Gary Thomas (gdt@linuxppc.org)
7 * VGA 'glass TTY' emulator
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Gary Thomas.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include <lib/libsa/stand.h>
37 #include <lib/libkern/libkern.h>
43 #define MONO_BASE 0x3B4
44 #define MONO_BUF 0xB0000
45 #define CGA_BASE 0x3D4
46 #define CGA_BUF 0xB8000
48 u_char background
= 0; /* Black */
49 u_char foreground
= 7; /* White */
57 * The current state of virtual displays
60 u_short
*cp
; /* the current character address */
62 NORMAL
, /* no pending escape */
65 EBRACEQ
/* saw ESC[= */
66 } state
; /* command parser state */
67 int cx
; /* the first escape seq argument */
68 int cy
; /* the second escap seq argument */
69 int *accp
; /* pointer to the current processed argument */
70 int row
; /* current column */
71 int so
; /* standout mode */
72 u_short color
; /* normal character color */
73 u_short color_so
; /* standout color */
74 u_short save_color
; /* saved normal color */
75 u_short save_color_so
; /* saved standout color */
79 * Color and attributes for normal, standout and kernel output
80 * are stored in the least-significant byte of a u_short
81 * so they don't have to be shifted for use.
82 * This is all byte-order dependent.
84 #define CATTR(x) (x) /* store color/attributes un-shifted */
85 #define ATTR_ADDR(which) (((u_char *)&(which))+1) /* address of attributes */
87 u_short pccolor
; /* color/attributes for tty output */
88 u_short pccolor_so
; /* color/attributes, standout mode */
90 static void cursor(void);
91 static void initscreen(void);
92 void fillw(u_short
, u_short
*, int);
97 * cursor() sets an offset (0-1999) into the 80x25 text area
102 int pos
= screen
.cp
- Crtat
;
104 if (lastpos
!= pos
) {
106 outb(addr_6845
+1, pos
>> 8);
108 outb(addr_6845
+1, pos
);
116 struct screen
*d
= &screen
;
118 pccolor
= CATTR((background
<<4)|foreground
);
119 pccolor_so
= CATTR((foreground
<<4)|background
);
121 d
->save_color
= pccolor
;
122 d
->color_so
= pccolor_so
;
123 d
->save_color_so
= pccolor_so
;
127 #define wrtchar(c, d) { \
134 fillw(u_short val
, u_short
*buf
, int num
)
136 /* Need to byte swap value */
145 * vga_putc (nee sput) has support for emulation of the 'ibmpc' termcap entry.
146 * This is a bare-bones implementation of a bare-bones entry
147 * One modification: Change li#24 to li#25 to reflect 25 lines
148 * "ca" is the color/attributes value (left-shifted by 8)
149 * or 0 if the current regular color for that screen is to be used.
154 struct screen
*d
= &screen
;
164 case 0x0: /* Ignore pad characters */
173 wrtchar(d
->color
| ' ', d
);
174 } while (d
->row
% 8);
177 case '\b': /* non-destructive backspace */
182 d
->row
+= COL
; /* prev column */
198 wrtchar(d
->color_so
|(c
<<8), d
);
200 wrtchar(d
->color
| (c
<<8), d
);
210 * In this state, the action at the end of the switch
211 * on the character type is to go to NORMAL state,
212 * and intermediate states do a return rather than break.
219 case 'A': /* back one row */
220 if (d
->cp
>= base
+ COL
)
224 case 'B': /* down one row */
228 case 'C': /* right cursor */
233 case 'D': /* left cursor */
238 d
->row
+= COL
; /* prev column ??? */
242 case 'J': /* Clear to end of display */
243 fillw(d
->color
|(' '<<8), d
->cp
, base
+ COL
* ROW
- d
->cp
);
246 case 'K': /* Clear to EOL */
247 fillw(d
->color
|(' '<<8), d
->cp
, COL
- (d
->cp
- base
) % COL
);
250 case 'H': /* Cursor move */
255 if (d
->cx
== 0 || d
->cy
== 0) {
259 d
->cp
= base
+ (d
->cx
- 1) * COL
+ d
->cy
- 1;
264 case '_': /* set cursor */
266 d
->cx
= 1; /* block */
268 d
->cx
= 12; /* underline */
270 outb(addr_6845
+1, d
->cx
);
272 outb(addr_6845
+1, 13);
275 case ';': /* Switch params in cursor def */
279 case '=': /* ESC[= color change */
283 case 'L': /* Insert line */
284 i
= (d
->cp
- base
) / COL
;
285 /* avoid deficiency of bcopy implementation */
286 /* XXX: comment and hack relevant? */
287 pp
= base
+ COL
* (ROW
-2);
288 for (j
= ROW
- 1 - i
; j
--; pp
-= COL
)
289 memmove(pp
+ COL
, pp
, COL
* CHR
);
290 fillw(d
->color
|(' '<<8), base
+ i
* COL
, COL
);
293 case 'M': /* Delete line */
294 i
= (d
->cp
- base
) / COL
;
296 memmove(pp
, pp
+ COL
, (ROW
-1 - i
)*COL
*CHR
);
297 fillw(d
->color
|(' '<<8), base
+ COL
* (ROW
- 1), COL
);
300 default: /* Only numbers valid here */
301 if ((c
>= '0') && (c
<= '9')) {
303 *(d
->accp
) += c
- '0';
313 * In this state, the action at the end of the switch
314 * on the character type is to go to NORMAL state,
315 * and intermediate states do a return rather than break.
320 * Set foreground/background color
321 * for normal mode, standout mode
323 * Based on code from kentp@svmp03.
327 colp
= ATTR_ADDR(d
->color
);
329 *colp
= (*colp
& 0xf0) | (d
->cx
);
333 colp
= ATTR_ADDR(d
->color
);
335 *colp
= (*colp
& 0xf) | (d
->cx
<< 4);
339 colp
= ATTR_ADDR(d
->color_so
);
343 colp
= ATTR_ADDR(d
->color_so
);
347 d
->save_color
= d
->color
;
348 d
->save_color_so
= d
->color_so
;
352 d
->color
= d
->save_color
;
353 d
->color_so
= d
->save_color_so
;
356 default: /* Only numbers valid here */
357 if ((c
>= '0') && (c
<= '9')) {
370 case 'c': /* Clear screen & home */
371 fillw(d
->color
|(' '<<8), base
, COL
* ROW
);
376 case '[': /* Start ESC [ sequence */
382 default: /* Invalid, clear state */
388 if (d
->cp
>= base
+ (COL
* ROW
)) { /* scroll check */
389 memmove(base
, base
+ COL
, COL
* (ROW
- 1) * CHR
);
390 fillw(d
->color
|(' '<<8), base
+ COL
* (ROW
- 1), COL
);
411 outb(0x3C5, inb(0x3C5) & ~0x20);
420 outb(0x3C5, inb(0x3C5) | 0x20);
424 vga_init(u_char
*ISA_mem
)
426 struct screen
*d
= &screen
;
428 memset(d
, 0, sizeof (screen
));
431 d
->cp
= Crtat
= (u_short
*)&ISA_mem
[0x0B8000];
432 addr_6845
= CGA_BASE
;
434 fillw(pccolor
|(' '<<8), d
->cp
, COL
* ROW
);
436 #endif /* CONS_VGA */