xref: /illumos-gate/usr/src/uts/i86pc/boot/boot_vga.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Miniature VGA driver for bootstrap.
31  */
32 
33 #include <sys/archsystm.h>
34 #include <sys/vgareg.h>
35 
36 #include "boot_vga.h"
37 
38 #if defined(_BOOT)
39 #include "../dboot/dboot_asm.h"
40 #include "../dboot/dboot_xboot.h"
41 #endif
42 
43 #define	VGA_COLOR_CRTC_INDEX	0x3d4
44 #define	VGA_COLOR_CRTC_DATA	0x3d5
45 
46 #if defined(__xpv) && defined(_BOOT)
47 
48 /*
49  * Device memory address
50  *
51  * In dboot under the hypervisor we don't have any memory mappings
52  * for the first meg of low memory so we can't access devices there.
53  * Intead we've mapped the device memory that we need to access into
54  * a local variable within dboot so we can access the device memory
55  * there.
56  */
57 extern unsigned short *video_fb;
58 #define	VGA_SCREEN		((unsigned short *)video_fb)
59 
60 #else /* __xpv && _BOOT */
61 
62 /* Device memory address */
63 #define	VGA_SCREEN		((unsigned short *)0xb8000)
64 
65 #endif /* __xpv && _BOOT */
66 
67 
68 static void vga_set_crtc(int index, unsigned char val);
69 static unsigned char vga_get_crtc(int index);
70 
71 void
72 vga_cursor_display(void)
73 {
74 	unsigned char val, msl;
75 
76 	/*
77 	 * Figure out the maximum scan line value.  We need this to set the
78 	 * cursor size.
79 	 */
80 	msl = vga_get_crtc(VGA_CRTC_MAX_S_LN) & 0x1f;
81 
82 	/*
83 	 * Enable the cursor and set it's size.  Preserve the upper two
84 	 * bits of the control register.
85 	 * - Bits 0-4 are the starting scan line of the cursor.
86 	 *   Scanning is done from top-to-bottom.  The top-most scan
87 	 *   line is 0 and the bottom most scan line is the maximum scan
88 	 *   line value.
89 	 * - Bit 5 is the cursor disable bit.
90 	 */
91 	val = vga_get_crtc(VGA_CRTC_CSSL);
92 	vga_set_crtc(VGA_CRTC_CSSL, (val & 0xc) | ((msl - 2) & 0x1f));
93 
94 	/*
95 	 * Continue setting the cursors size.
96 	 * - Bits 0-4 are the ending scan line of the cursor.
97 	 *   Scanning is done from top-to-bottom.  The top-most scan
98 	 *   line is 0 and the bottom most scan line is the maximum scan
99 	 *   line value.
100 	 * - Bits 5-6 are the cursor skew.
101 	 */
102 	vga_set_crtc(VGA_CRTC_CESL, msl);
103 }
104 
105 
106 void
107 vga_clear(int color)
108 {
109 	unsigned short val;
110 	int i;
111 
112 	val = (color << 8) | ' ';
113 
114 	for (i = 0; i < VGA_TEXT_ROWS * VGA_TEXT_COLS; i++) {
115 		VGA_SCREEN[i] = val;
116 	}
117 }
118 
119 void
120 vga_drawc(int c, int color)
121 {
122 	int row;
123 	int col;
124 
125 	vga_getpos(&row, &col);
126 	VGA_SCREEN[row*VGA_TEXT_COLS + col] = (color << 8) | c;
127 }
128 
129 void
130 vga_scroll(int color)
131 {
132 	unsigned short val;
133 	int i;
134 
135 	val = (color << 8) | ' ';
136 
137 	for (i = 0; i < (VGA_TEXT_ROWS-1)*VGA_TEXT_COLS; i++) {
138 		VGA_SCREEN[i] = VGA_SCREEN[i + VGA_TEXT_COLS];
139 	}
140 	for (; i < VGA_TEXT_ROWS * VGA_TEXT_COLS; i++) {
141 		VGA_SCREEN[i] = val;
142 	}
143 }
144 
145 void
146 vga_setpos(int row, int col)
147 {
148 	int off;
149 
150 	off = row * VGA_TEXT_COLS + col;
151 	vga_set_crtc(VGA_CRTC_CLAH, off >> 8);
152 	vga_set_crtc(VGA_CRTC_CLAL, off & 0xff);
153 }
154 
155 void
156 vga_getpos(int *row, int *col)
157 {
158 	int off;
159 
160 	off = (vga_get_crtc(VGA_CRTC_CLAH) << 8) + vga_get_crtc(VGA_CRTC_CLAL);
161 	*row = off / VGA_TEXT_COLS;
162 	*col = off % VGA_TEXT_COLS;
163 }
164 
165 static void
166 vga_set_crtc(int index, unsigned char val)
167 {
168 	outb(VGA_COLOR_CRTC_INDEX, index);
169 	outb(VGA_COLOR_CRTC_DATA, val);
170 }
171 
172 static unsigned char
173 vga_get_crtc(int index)
174 {
175 	outb(VGA_COLOR_CRTC_INDEX, index);
176 	return (inb(VGA_COLOR_CRTC_DATA));
177 }
178