xref: /illumos-gate/usr/src/common/vga/vgasubr.c (revision 0250c53ad267726f2438e3c6556199a0bbf588a2)
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 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  * Copyright 2018 Toomas Soome <tsoome@me.com>
26  */
27 
28 /*
29  * Support routines for VGA drivers
30  */
31 
32 #if defined(_KERNEL)
33 #include <sys/debug.h>
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/time.h>
37 #include <sys/buf.h>
38 #include <sys/errno.h>
39 #include <sys/systm.h>
40 #include <sys/conf.h>
41 
42 #include <sys/cmn_err.h>
43 
44 #include <sys/kmem.h>
45 #include <sys/conf.h>
46 #include <sys/ddi.h>
47 #include <sys/devops.h>
48 #include <sys/sunddi.h>
49 
50 #include <sys/modctl.h>
51 
52 #define	PUTB(reg, off, v)	ddi_put8(reg->handle, reg->addr + (off), v)
53 #define	GETB(reg, off)		ddi_get8(reg->handle, reg->addr + (off))
54 
55 #elif defined(_STANDALONE)
56 
57 #include <stand.h>
58 #include <machine/cpufunc.h>
59 
60 #define	PUTB(reg, off, v)	outb(reg + (off), v)
61 #define	GETB(reg, off)		inb(reg + (off))
62 #endif
63 
64 #include <sys/vgareg.h>
65 #include <sys/vgasubr.h>
66 
67 #define	GET_HORIZ_END(c)	vga_get_crtc(c, VGA_CRTC_H_D_END)
68 #define	GET_VERT_END(c)	(vga_get_crtc(c, VGA_CRTC_VDE) \
69 	+ (((vga_get_crtc(c, VGA_CRTC_OVFL_REG) >> \
70 	    VGA_CRTC_OVFL_REG_VDE8) & 1) << 8) \
71 	+ (((vga_get_crtc(c, VGA_CRTC_OVFL_REG) >> \
72 	    VGA_CRTC_OVFL_REG_VDE9) & 1) << 9))
73 
74 #define	GET_VERT_X2(c)	\
75 	(vga_get_crtc(c, VGA_CRTC_CRT_MD) & VGA_CRTC_CRT_MD_VT_X2)
76 
77 unsigned char VGA_CRTC_TEXT[NUM_CRTC_REG] = {
78 	0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
79 	0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x05, 0x00,
80 	0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
81 	0xff };
82 unsigned char VGA_SEQ_TEXT[NUM_SEQ_REG] = {
83 	0x03, 0x00, 0x03, 0x00, 0x02 };
84 unsigned char VGA_GRC_TEXT[NUM_GRC_REG] = {
85 	0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff };
86 unsigned char VGA_ATR_TEXT[NUM_ATR_REG] = {
87 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
88 	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
89 	0x0c, 0x00, 0x0f, 0x08, 0x00 };
90 
91 void
92 vga_get_hardware_settings(vgaregmap_t reg, int *width, int *height)
93 {
94 	*width = (GET_HORIZ_END(reg)+1)*8;
95 	*height = GET_VERT_END(reg)+1;
96 	if (GET_VERT_X2(reg)) *height *= 2;
97 }
98 
99 int
100 vga_get_reg(vgaregmap_t reg, int indexreg)
101 {
102 	return (GETB(reg, indexreg));
103 }
104 
105 void
106 vga_set_reg(vgaregmap_t reg, int indexreg, int v)
107 {
108 	PUTB(reg, indexreg, v);
109 }
110 
111 int
112 vga_get_crtc(vgaregmap_t reg, int i)
113 {
114 	return (vga_get_indexed(reg, VGA_CRTC_ADR, VGA_CRTC_DATA, i));
115 }
116 
117 void
118 vga_set_crtc(vgaregmap_t reg, int i, int v)
119 {
120 	vga_set_indexed(reg, VGA_CRTC_ADR, VGA_CRTC_DATA, i, v);
121 }
122 
123 int
124 vga_get_seq(vgaregmap_t reg, int i)
125 {
126 	return (vga_get_indexed(reg, VGA_SEQ_ADR, VGA_SEQ_DATA, i));
127 }
128 
129 void
130 vga_set_seq(vgaregmap_t reg, int i, int v)
131 {
132 	vga_set_indexed(reg, VGA_SEQ_ADR, VGA_SEQ_DATA, i, v);
133 }
134 
135 int
136 vga_get_grc(vgaregmap_t reg, int i)
137 {
138 	return (vga_get_indexed(reg, VGA_GRC_ADR, VGA_GRC_DATA, i));
139 }
140 
141 void
142 vga_set_grc(vgaregmap_t reg, int i, int v)
143 {
144 	vga_set_indexed(reg, VGA_GRC_ADR, VGA_GRC_DATA, i, v);
145 }
146 
147 int
148 vga_get_atr(vgaregmap_t reg, int i)
149 {
150 	int ret;
151 
152 	(void) GETB(reg, CGA_STAT);
153 	PUTB(reg, VGA_ATR_AD, i);
154 	ret = GETB(reg, VGA_ATR_DATA);
155 
156 	(void) GETB(reg, CGA_STAT);
157 	PUTB(reg, VGA_ATR_AD, VGA_ATR_ENB_PLT);
158 
159 	return (ret);
160 }
161 
162 void
163 vga_set_atr(vgaregmap_t reg, int i, int v)
164 {
165 	(void) GETB(reg, CGA_STAT);
166 	PUTB(reg, VGA_ATR_AD, i);
167 	PUTB(reg, VGA_ATR_AD, v);
168 
169 	(void) GETB(reg, CGA_STAT);
170 	PUTB(reg, VGA_ATR_AD, VGA_ATR_ENB_PLT);
171 }
172 
173 void
174 vga_set_indexed(
175 	vgaregmap_t reg,
176 	int indexreg,
177 	int datareg,
178 	unsigned char index,
179 	unsigned char val)
180 {
181 	PUTB(reg, indexreg, index);
182 	PUTB(reg, datareg, val);
183 }
184 
185 int
186 vga_get_indexed(
187 	vgaregmap_t reg,
188 	int indexreg,
189 	int datareg,
190 	unsigned char index)
191 {
192 	PUTB(reg, indexreg, index);
193 	return (GETB(reg, datareg));
194 }
195 
196 /*
197  * VGA DAC access functions
198  * Note:  These assume a VGA-style 6-bit DAC.  Some DACs are 8 bits
199  * wide.  These functions are not appropriate for those DACs.
200  */
201 void
202 vga_put_cmap(
203 	vgaregmap_t reg,
204 	int index,
205 	unsigned char r,
206 	unsigned char g,
207 	unsigned char b)
208 {
209 
210 	PUTB(reg, VGA_DAC_WR_AD, index);
211 	PUTB(reg, VGA_DAC_DATA, r >> 2);
212 	PUTB(reg, VGA_DAC_DATA, g >> 2);
213 	PUTB(reg, VGA_DAC_DATA, b >> 2);
214 }
215 
216 void
217 vga_get_cmap(
218 	vgaregmap_t reg,
219 	int index,
220 	unsigned char *r,
221 	unsigned char *g,
222 	unsigned char *b)
223 {
224 	PUTB(reg, VGA_DAC_RD_AD, index);
225 	*r = GETB(reg, VGA_DAC_DATA) << 2;
226 	*g = GETB(reg, VGA_DAC_DATA) << 2;
227 	*b = GETB(reg, VGA_DAC_DATA) << 2;
228 }
229 
230 #ifdef	DEBUG
231 
232 void
233 vga_dump_regs(vgaregmap_t reg, int maxseq, int maxcrtc, int maxatr, int maxgrc)
234 {
235 	int i, j;
236 
237 	printf("Sequencer regs:\n");
238 	for (i = 0; i < maxseq; i += 0x10) {
239 		printf("%2x:  ", i);
240 		for (j = 0; j < 0x08; j++) {
241 			printf("%2x ", vga_get_seq(reg, i+j));
242 		}
243 		printf("- ");
244 		for (; j < 0x10; j++) {
245 			printf("%2x ", vga_get_seq(reg, i+j));
246 		}
247 		printf("\n");
248 	}
249 	printf("\nCRT Controller regs:\n");
250 	for (i = 0; i < maxcrtc; i += 0x10) {
251 		printf("%2x:  ", i);
252 		for (j = 0; j < 0x08; j++) {
253 			printf("%2x ", vga_get_crtc(reg, i+j));
254 		}
255 		printf("- ");
256 		for (; j < 0x10; j++) {
257 			printf("%2x ", vga_get_crtc(reg, i+j));
258 		}
259 		printf("\n");
260 	}
261 	printf("\nAttribute Controller regs:\n");
262 	for (i = 0; i < maxatr; i += 0x10) {
263 		printf("%2x:  ", i);
264 		for (j = 0; j < 0x08; j++) {
265 			printf("%2x ", vga_get_atr(reg, i+j));
266 		}
267 		printf("- ");
268 		for (; j < 0x10; j++) {
269 			printf("%2x ", vga_get_atr(reg, i+j));
270 		}
271 		printf("\n");
272 	}
273 	printf("\nGraphics Controller regs:\n");
274 	for (i = 0; i < maxgrc; i += 0x10) {
275 		printf("%2x:  ", i);
276 		for (j = 0; j < 0x08; j++) {
277 			printf("%2x ", vga_get_grc(reg, i+j));
278 		}
279 		printf("- ");
280 		for (; j < 0x10; j++) {
281 			printf("%2x ", vga_get_grc(reg, i+j));
282 		}
283 		printf("\n");
284 	}
285 }
286 #endif	/* DEBUG */
287 
288 /*
289  * VGA 80X25 text mode standard palette
290  */
291 unsigned char VGA_TEXT_PALETTES[64][3] = {
292 	{ 0x00, 0x00, 0x00 },
293 	{ 0x00, 0x00, 0x2A },
294 	{ 0x00, 0x2A, 0x00 },
295 	{ 0x00, 0x2A, 0x2A },
296 	{ 0x2A, 0x00, 0x00 },
297 	{ 0x2A, 0x00, 0x2A },
298 	{ 0x2A, 0x2A, 0x00 },
299 	{ 0x2A, 0x2A, 0x2A },
300 	{ 0x00, 0x00, 0x15 },
301 	{ 0x00, 0x00, 0x3F },
302 	{ 0x00, 0x2A, 0x15 },
303 	{ 0x00, 0x2A, 0x3F },
304 	{ 0x2A, 0x00, 0x15 },
305 	{ 0x2A, 0x00, 0x3F },
306 	{ 0x2A, 0x2A, 0x15 },
307 	{ 0x2A, 0x2A, 0x3F },
308 	{ 0x00, 0x15, 0x00 },
309 	{ 0x00, 0x15, 0x2A },
310 	{ 0x00, 0x3F, 0x00 },
311 	{ 0x00, 0x3F, 0x2A },
312 	{ 0x2A, 0x15, 0x00 },
313 	{ 0x2A, 0x15, 0x2A },
314 	{ 0x2A, 0x3F, 0x00 },
315 	{ 0x2A, 0x3F, 0x2A },
316 	{ 0x00, 0x15, 0x15 },
317 	{ 0x00, 0x15, 0x3F },
318 	{ 0x00, 0x3F, 0x15 },
319 	{ 0x00, 0x3F, 0x3F },
320 	{ 0x2A, 0x15, 0x15 },
321 	{ 0x2A, 0x15, 0x3F },
322 	{ 0x2A, 0x3F, 0x15 },
323 	{ 0x2A, 0x3F, 0x3F },
324 	{ 0x15, 0x00, 0x00 },
325 	{ 0x15, 0x00, 0x2A },
326 	{ 0x15, 0x2A, 0x00 },
327 	{ 0x15, 0x2A, 0x2A },
328 	{ 0x3F, 0x00, 0x00 },
329 	{ 0x3F, 0x00, 0x2A },
330 	{ 0x3F, 0x2A, 0x00 },
331 	{ 0x3F, 0x2A, 0x2A },
332 	{ 0x15, 0x00, 0x15 },
333 	{ 0x15, 0x00, 0x3F },
334 	{ 0x15, 0x2A, 0x15 },
335 	{ 0x15, 0x2A, 0x3F },
336 	{ 0x3F, 0x00, 0x15 },
337 	{ 0x3F, 0x00, 0x3F },
338 	{ 0x3F, 0x2A, 0x15 },
339 	{ 0x3F, 0x2A, 0x3F },
340 	{ 0x15, 0x15, 0x00 },
341 	{ 0x15, 0x15, 0x2A },
342 	{ 0x15, 0x3F, 0x00 },
343 	{ 0x15, 0x3F, 0x2A },
344 	{ 0x3F, 0x15, 0x00 },
345 	{ 0x3F, 0x15, 0x2A },
346 	{ 0x3F, 0x3F, 0x00 },
347 	{ 0x3F, 0x3F, 0x2A },
348 	{ 0x15, 0x15, 0x15 },
349 	{ 0x15, 0x15, 0x3F },
350 	{ 0x15, 0x3F, 0x15 },
351 	{ 0x15, 0x3F, 0x3F },
352 	{ 0x3F, 0x15, 0x15 },
353 	{ 0x3F, 0x15, 0x3F },
354 	{ 0x3F, 0x3F, 0x15 },
355 	{ 0x3F, 0x3F, 0x3F }
356 };
357