vreset.c revision 1.3.8.1 1 /* $NetBSD: vreset.c,v 1.3.8.1 2006/04/19 02:33:39 elad Exp $ */
2 /*-
3 * Copyright (c) 2006 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Tim Rightnour
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
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 the NetBSD
20 * Foundation, Inc. and its contributors.
21 * 4. Neither the name of The NetBSD Foundation nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #ifdef VGA_RESET
39 #include <lib/libsa/stand.h>
40 #include "boot.h"
41 #include "iso_font.h"
42
43 #define VGA_SR_PORT 0x3c4
44 #define VGA_CR_PORT 0x3d4
45 #define VGA_CR_DATA 0x3d5
46 #define VGA_GR_PORT 0x3ce
47 #define VGA_GR_DATA 0x3cf
48 #define SRREGS 4
49 #define CRREGS 24
50 #define GRREGS 9
51 #define LINES 25
52 #define COLS 80
53 #define PCI_VENDOR_S3 0x5333
54 #define PCI_VENDOR_CIRRUS 0x1013
55 #define PCI_VENDOR_DIAMOND 0x100E
56 #define PCI_VENDOR_MATROX 0x102B
57 #define PCI_VENDOR_PARADISE 0x101C
58
59 static void write_attr(u_int8_t, u_int8_t, u_int8_t);
60 static void set_text_regs(void);
61 static void set_text_clut(int);
62 static void load_font(u_int8_t *);
63 static void unlock_S3(void);
64 static void clear_video_memory(void);
65
66 extern char *videomem;
67
68 typedef struct vga_reg {
69 u_int8_t idx;
70 u_int8_t val;
71 } vga_reg_t;
72
73 static vga_reg_t SR_regs[SRREGS] = {
74 /* idx val */
75 { 0x1, 0x0 }, /* 01: clocking mode */
76 { 0x2, 0x3 }, /* 02: map mask */
77 { 0x3, 0x0 }, /* 03: character map select */
78 { 0x4, 0x2 } /* 04: memory mode */
79 };
80
81 static vga_reg_t CR_regs[CRREGS] = {
82 /* idx val */
83 { 0x0, 0x61 }, /* 00: horizontal total */
84 { 0x1, 0x4f }, /* 01: horizontal display-enable end */
85 { 0x2, 0x50 }, /* 02: start horizontal blanking */
86 { 0x3, 0x82 }, /* 03: display skew control / end horizontal blanking */ { 0x4, 0x55 }, /* 04: start horizontal retrace pulse */
87 { 0x5, 0x81 }, /* 05: horizontal retrace delay / end horiz. retrace */
88 { 0x6, 0xf0 }, /* 06: vertical total */
89 { 0x7, 0x1f }, /* 07: overflow register */
90 { 0x8, 0x00 }, /* 08: preset row scan */
91 { 0x9, 0x4f }, /* 09: overflow / maximum scan line */
92 { 0xa, 0x0d }, /* 0A: cursor off / cursor start */
93 { 0xb, 0x0e }, /* 0B: cursor skew / cursor end */
94 { 0xc, 0x00 }, /* 0C: start regenerative buffer address high */
95 { 0xd, 0x00 }, /* 0D: start regenerative buffer address low */
96 { 0xe, 0x00 }, /* 0E: cursor location high */
97 { 0xf, 0x00 }, /* 0F: cursor location low */
98 { 0x10, 0x9a }, /* 10: vertical retrace start */
99 { 0x11, 0x8c }, /* 11: vertical interrupt / vertical retrace end */
100 { 0x12, 0x8f }, /* 12: vertical display enable end */
101 { 0x13, 0x28 }, /* 13: logical line width */
102 { 0x14, 0x1f }, /* 14: underline location */
103 { 0x15, 0x97 }, /* 15: start vertical blanking */
104 { 0x16, 0x00 }, /* 16: end vertical blanking */
105 { 0x17, 0xa3 }, /* 17: CRT mode control */
106 };
107
108 static vga_reg_t GR_regs[GRREGS] = {
109 /* idx val */
110 { 0x0, 0x00 }, /* 00: set/reset map */
111 { 0x1, 0x00 }, /* 01: enable set/reset */
112 { 0x2, 0x00 }, /* 02: color compare */
113 { 0x3, 0x00 }, /* 03: data rotate */
114 { 0x4, 0x00 }, /* 04: read map select */
115 { 0x5, 0x10 }, /* 05: graphics mode */
116 { 0x6, 0x0e }, /* 06: miscellaneous */
117 { 0x7, 0x00 }, /* 07: color don't care */
118 { 0x8, 0xff }, /* 08: bit mask */
119 };
120
121 /* video DAC palette registers */
122 /* XXX only set up 16 colors used by internal palette in ATC regsters */
123 static const u_int8_t vga_dacpal[] = {
124 /* R G B */
125 0x00, 0x00, 0x00, /* BLACK */
126 0x00, 0x00, 0x2a, /* BLUE */
127 0x00, 0x2a, 0x00, /* GREEN */
128 0x00, 0x2a, 0x2a, /* CYAN */
129 0x2a, 0x00, 0x00, /* RED */
130 0x2a, 0x00, 0x2a, /* MAGENTA */
131 0x2a, 0x15, 0x00, /* BROWN */
132 0x2a, 0x2a, 0x2a, /* LIGHTGREY */
133 0x15, 0x15, 0x15, /* DARKGREY */
134 0x15, 0x15, 0x3f, /* LIGHTBLUE */
135 0x15, 0x3f, 0x15, /* LIGHTGREEN */
136 0x15, 0x3f, 0x3f, /* LIGHTCYAN */
137 0x3f, 0x15, 0x15, /* LIGHTRED */
138 0x3f, 0x15, 0x3f, /* LIGHTMAGENTA */
139 0x3f, 0x3f, 0x15, /* YELLOW */
140 0x3f, 0x3f, 0x3f /* WHITE */
141 };
142
143 static const u_int8_t vga_atc[] = {
144 0x00, /* 00: internal palette 0 */
145 0x01, /* 01: internal palette 1 */
146 0x02, /* 02: internal palette 2 */
147 0x03, /* 03: internal palette 3 */
148 0x04, /* 04: internal palette 4 */
149 0x05, /* 05: internal palette 5 */
150 0x14, /* 06: internal palette 6 */
151 0x07, /* 07: internal palette 7 */
152 0x38, /* 08: internal palette 8 */
153 0x39, /* 09: internal palette 9 */
154 0x3a, /* 0A: internal palette 10 */
155 0x3b, /* 0B: internal palette 11 */
156 0x3c, /* 0C: internal palette 12 */
157 0x3d, /* 0D: internal palette 13 */
158 0x3e, /* 0E: internal palette 14 */
159 0x3f, /* 0F: internal palette 15 */
160 0x0c, /* 10: attribute mode control */
161 0x00, /* 11: overscan color */
162 0x0f, /* 12: color plane enable */
163 0x08, /* 13: horizontal PEL panning */
164 0x00 /* 14: color select */
165 };
166
167 void
168 vga_reset(u_char *ISA_mem)
169 {
170 int slot;
171
172 /* check if we are in text mode, if so, punt */
173 outb(VGA_GR_PORT, 0x06);
174 if ((inb(VGA_GR_DATA) & 0x01) == 0)
175 return;
176
177 /* guess not, we lose. */
178 slot = -1;
179 while ((slot = scan_PCI(slot)) > -1) {
180 unlockVideo(slot);
181 switch (PCI_vendor(slot)) {
182 case PCI_VENDOR_CIRRUS:
183 outw(VGA_SR_PORT, 0x0612); /* unlock ext regs */
184 outw(VGA_SR_PORT, 0x0700); /* reset ext sequence mode */
185 break;
186 case PCI_VENDOR_PARADISE:
187 outw(VGA_GR_PORT, 0x0f05); /* unlock registers */
188 outw(VGA_SR_PORT, 0x0648);
189 outw(VGA_CR_PORT, 0x2985);
190 outw(VGA_CR_PORT, 0x34a6);
191 outb(VGA_GR_PORT, 0x0b); /* disable linear addressing */
192 outb(VGA_GR_DATA, inb(VGA_GR_DATA) & ~0x30);
193 outw(VGA_SR_PORT, 0x1400);
194 outb(VGA_GR_PORT, 0x0e); /* disable 256 color mode */
195 outb(VGA_GR_DATA, inb(VGA_GR_DATA) & ~0x01);
196 outb(0xd00, 0xff); /* enable auto-centering */
197 if (!(inb(0xd01) & 0x03)) {
198 outb(VGA_CR_PORT, 0x33);
199 outb(VGA_CR_DATA, inb(VGA_CR_DATA) & ~0x90);
200 outb(VGA_CR_PORT, 0x32);
201 outb(VGA_CR_DATA, inb(VGA_CR_DATA) | 0x04);
202 outw(VGA_CR_PORT, 0x0250);
203 outw(VGA_CR_PORT, 0x07ba);
204 outw(VGA_CR_PORT, 0x0900);
205 outw(VGA_CR_PORT, 0x15e7);
206 outw(VGA_CR_PORT, 0x2a95);
207 }
208 outw(VGA_CR_PORT, 0x34a0);
209 break;
210 case PCI_VENDOR_S3:
211 unlock_S3();
212 break;
213 default:
214 break;
215 }
216 outw(VGA_SR_PORT, 0x0120); /* disable video */
217 set_text_regs();
218 set_text_clut(0);
219 load_font(ISA_mem);
220 set_text_regs();
221 outw(VGA_SR_PORT, 0x0100); /* re-enable video */
222 clear_video_memory();
223
224 if (PCI_vendor(slot) == PCI_VENDOR_S3)
225 outb(0x3c2, 0x63); /* ??? */
226 delay(1000);
227 }
228 return;
229 }
230
231 /* write something to a VGA attribute register */
232 static void
233 write_attr(u_int8_t index, u_int8_t data, u_int8_t videoOn)
234 {
235 u_int8_t v;
236
237 v = inb(0x3da); /* reset attr addr toggle */
238 if (videoOn)
239 outb(0x3c0, (index & 0x1F) | 0x20);
240 else
241 outb(0x3c0, (index & 0x1F));
242 outb(0x3c0, data);
243 }
244
245 static void
246 set_text_regs(void)
247 {
248 int i;
249
250 for (i = 0; i < SRREGS; i++) {
251 outb(VGA_SR_PORT, SR_regs[i].idx);
252 outb(VGA_SR_PORT + 1, SR_regs[i].val);
253 }
254 for (i = 0; i < CRREGS; i++) {
255 outb(VGA_CR_PORT, CR_regs[i].idx);
256 outb(VGA_CR_PORT + 1, CR_regs[i].val);
257 }
258 for (i = 0; i < GRREGS; i++) {
259 outb(VGA_GR_PORT, GR_regs[i].idx);
260 outb(VGA_GR_PORT + 1, GR_regs[i].val);
261 }
262
263 outb(0x3c2, 0x67); /* MISC */
264 outb(0x3c6, 0xff); /* MASK */
265
266 for (i = 0; i < 0x14; i++)
267 write_attr(i, vga_atc[i], 0);
268 write_attr(0x14, 0x00, 1); /* color select; video on */
269 }
270
271 static void
272 set_text_clut(int shift)
273 {
274 int i;
275
276 outb(0x3C6, 0xFF);
277 inb(0x3C7);
278 outb(0x3C8, 0);
279 inb(0x3C7);
280
281 for (i = 0; i < (16 * 3); ) {
282 outb(0x3c9, vga_dacpal[i++] << shift);
283 outb(0x3c9, vga_dacpal[i++] << shift);
284 outb(0x3c9, vga_dacpal[i++] << shift);
285 }
286 }
287
288 static void
289 load_font(u_int8_t *ISA_mem)
290 {
291 int i, j;
292 u_int8_t *font_page = (u_int8_t *)&ISA_mem[0xA0000];
293
294 outb(0x3C2, 0x67);
295 inb(0x3DA); /* Reset Attr toggle */
296
297 outb(0x3C0, 0x30);
298 outb(0x3C0, 0x01); /* graphics mode */
299 outw(0x3C4, 0x0001); /* reset sequencer */
300 outw(0x3C4, 0x0204); /* write to plane 2 */
301 outw(0x3C4, 0x0406); /* enable plane graphics */
302 outw(0x3C4, 0x0003); /* reset sequencer */
303 outw(0x3CE, 0x0402); /* read plane 2 */
304 outw(0x3CE, 0x0500); /* write mode 0, read mode 0 */
305 outw(0x3CE, 0x0605); /* set graphics mode */
306
307 for (i = 0; i < sizeof(font); i += 16) {
308 for (j = 0; j < 16; j++) {
309 __asm__ volatile("eieio");
310 font_page[(2*i)+j] = font[i+j];
311 }
312 }
313 }
314
315 static void
316 unlock_S3(void)
317 {
318 int s3_devid;
319
320 outw(VGA_CR_PORT, 0x3848);
321 outw(VGA_CR_PORT, 0x39a5);
322 outb(VGA_CR_PORT, 0x2d);
323 s3_devid = inb(VGA_CR_DATA) << 8;
324 outb(VGA_CR_PORT, 0x2e);
325 s3_devid |= inb(VGA_CR_DATA);
326
327 if (s3_devid != 0x8812) {
328 /* from the S3 manual */
329 outb(0x46E8, 0x10); /* Put into setup mode */
330 outb(0x3C3, 0x10);
331 outb(0x102, 0x01); /* Enable registers */
332 outb(0x46E8, 0x08); /* Enable video */
333 outb(0x3C3, 0x08);
334 outb(0x4AE8, 0x00);
335 outb(VGA_CR_PORT, 0x38); /* Unlock all registers */
336 outb(VGA_CR_DATA, 0x48);
337 outb(VGA_CR_PORT, 0x39);
338 outb(VGA_CR_DATA, 0xA5);
339 outb(VGA_CR_PORT, 0x40);
340 outb(VGA_CR_DATA, inb(0x3D5)|0x01);
341 outb(VGA_CR_PORT, 0x33);
342 outb(VGA_CR_DATA, inb(0x3D5)&~0x52);
343 outb(VGA_CR_PORT, 0x35);
344 outb(VGA_CR_DATA, inb(0x3D5)&~0x30);
345 outb(VGA_CR_PORT, 0x3A);
346 outb(VGA_CR_DATA, 0x00);
347 outb(VGA_CR_PORT, 0x53);
348 outb(VGA_CR_DATA, 0x00);
349 outb(VGA_CR_PORT, 0x31);
350 outb(VGA_CR_DATA, inb(0x3D5)&~0x4B);
351 outb(VGA_CR_PORT, 0x58);
352
353 outb(VGA_CR_DATA, 0);
354
355 outb(VGA_CR_PORT, 0x54);
356 outb(VGA_CR_DATA, 0x38);
357 outb(VGA_CR_PORT, 0x60);
358 outb(VGA_CR_DATA, 0x07);
359 outb(VGA_CR_PORT, 0x61);
360 outb(VGA_CR_DATA, 0x80);
361 outb(VGA_CR_PORT, 0x62);
362 outb(VGA_CR_DATA, 0xA1);
363 outb(VGA_CR_PORT, 0x69); /* High order bits for cursor address */
364 outb(VGA_CR_DATA, 0);
365
366 outb(VGA_CR_PORT, 0x32);
367 outb(VGA_CR_DATA, inb(0x3D5)&~0x10);
368 } else {
369 /* IBM Portable 860 */
370 outw(VGA_SR_PORT, 0x0806);
371 outw(VGA_SR_PORT, 0x1041);
372 outw(VGA_SR_PORT, 0x1128);
373 outw(VGA_CR_PORT, 0x4000);
374 outw(VGA_CR_PORT, 0x3100);
375 outw(VGA_CR_PORT, 0x3a05);
376 outw(VGA_CR_PORT, 0x6688);
377 outw(VGA_CR_PORT, 0x5800); /* disable linear addressing */
378 outw(VGA_CR_PORT, 0x4500); /* disable H/W cursor */
379 outw(VGA_SR_PORT, 0x5410); /* enable auto-centering */
380 outw(VGA_SR_PORT, 0x561f);
381 outw(VGA_SR_PORT, 0x1b80); /* lock DCLK selection */
382 outw(VGA_CR_PORT, 0x3900); /* lock S3 registers */
383 outw(VGA_CR_PORT, 0x3800);
384 }
385 }
386
387 static void
388 clear_video_memory(void)
389 {
390 int i, j;
391
392 for (i = 0; i < LINES; i++) {
393 for (j = 0; j < COLS; j++) {
394 videomem[((i * COLS)+j) * 2] = 0x20; /* space */
395 videomem[((i * COLS)+j) * 2 + 1] = 0x07; /* fg/bg */
396 }
397 }
398 }
399
400 #endif /* VGA_RESET */
401