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
vga_get_hardware_settings(vgaregmap_t reg,int * width,int * height)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
vga_get_reg(vgaregmap_t reg,int indexreg)100 vga_get_reg(vgaregmap_t reg, int indexreg)
101 {
102 return (GETB(reg, indexreg));
103 }
104
105 void
vga_set_reg(vgaregmap_t reg,int indexreg,int v)106 vga_set_reg(vgaregmap_t reg, int indexreg, int v)
107 {
108 PUTB(reg, indexreg, v);
109 }
110
111 int
vga_get_crtc(vgaregmap_t reg,int i)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
vga_set_crtc(vgaregmap_t reg,int i,int v)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
vga_get_seq(vgaregmap_t reg,int i)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
vga_set_seq(vgaregmap_t reg,int i,int v)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
vga_get_grc(vgaregmap_t reg,int i)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
vga_set_grc(vgaregmap_t reg,int i,int v)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
vga_get_atr(vgaregmap_t reg,int i)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
vga_set_atr(vgaregmap_t reg,int i,int v)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
vga_set_indexed(vgaregmap_t reg,int indexreg,int datareg,unsigned char index,unsigned char val)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
vga_get_indexed(vgaregmap_t reg,int indexreg,int datareg,unsigned char index)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
vga_put_cmap(vgaregmap_t reg,int index,unsigned char r,unsigned char g,unsigned char b)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
vga_get_cmap(vgaregmap_t reg,int index,unsigned char * r,unsigned char * g,unsigned char * b)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
vga_dump_regs(vgaregmap_t reg,int maxseq,int maxcrtc,int maxatr,int maxgrc)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