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 */
57extern 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
68static void vga_set_crtc(int index, unsigned char val);
69static unsigned char vga_get_crtc(int index);
70
71void
72vga_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
106void
107vga_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
119void
120vga_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
129void
130vga_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
145void
146vga_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
155void
156vga_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
165static void
166vga_set_crtc(int index, unsigned char val)
167{
168	outb(VGA_COLOR_CRTC_INDEX, index);
169	outb(VGA_COLOR_CRTC_DATA, val);
170}
171
172static unsigned char
173vga_get_crtc(int index)
174{
175	outb(VGA_COLOR_CRTC_INDEX, index);
176	return (inb(VGA_COLOR_CRTC_DATA));
177}
178