vreset.c revision 1.3.2.1 1 /* $NetBSD: vreset.c,v 1.3.2.1 2006/09/09 02:42:44 rpaulo 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, cardfound;
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 cardfound = 0;
181 switch (PCI_vendor(slot)) {
182 case PCI_VENDOR_CIRRUS:
183 unlockVideo(slot);
184 outw(VGA_SR_PORT, 0x0612); /* unlock ext regs */
185 outw(VGA_SR_PORT, 0x0700); /* reset ext sequence mode */
186 cardfound++;
187 break;
188 case PCI_VENDOR_PARADISE:
189 unlockVideo(slot);
190 outw(VGA_GR_PORT, 0x0f05); /* unlock registers */
191 outw(VGA_SR_PORT, 0x0648);
192 outw(VGA_CR_PORT, 0x2985);
193 outw(VGA_CR_PORT, 0x34a6);
194 outb(VGA_GR_PORT, 0x0b); /* disable linear addressing */
195 outb(VGA_GR_DATA, inb(VGA_GR_DATA) & ~0x30);
196 outw(VGA_SR_PORT, 0x1400);
197 outb(VGA_GR_PORT, 0x0e); /* disable 256 color mode */
198 outb(VGA_GR_DATA, inb(VGA_GR_DATA) & ~0x01);
199 outb(0xd00, 0xff); /* enable auto-centering */
200 if (!(inb(0xd01) & 0x03)) {
201 outb(VGA_CR_PORT, 0x33);
202 outb(VGA_CR_DATA, inb(VGA_CR_DATA) & ~0x90);
203 outb(VGA_CR_PORT, 0x32);
204 outb(VGA_CR_DATA, inb(VGA_CR_DATA) | 0x04);
205 outw(VGA_CR_PORT, 0x0250);
206 outw(VGA_CR_PORT, 0x07ba);
207 outw(VGA_CR_PORT, 0x0900);
208 outw(VGA_CR_PORT, 0x15e7);
209 outw(VGA_CR_PORT, 0x2a95);
210 }
211 outw(VGA_CR_PORT, 0x34a0);
212 cardfound++;
213 break;
214 case PCI_VENDOR_S3:
215 unlockVideo(slot);
216 unlock_S3();
217 cardfound++;
218 break;
219 default:
220 break;
221 }
222 if (cardfound) {
223 outw(VGA_SR_PORT, 0x0120); /* disable video */
224 set_text_regs();
225 set_text_clut(0);
226 load_font(ISA_mem);
227 set_text_regs();
228 outw(VGA_SR_PORT, 0x0100); /* re-enable video */
229 clear_video_memory();
230
231 if (PCI_vendor(slot) == PCI_VENDOR_S3)
232 outb(0x3c2, 0x63); /* ??? */
233 delay(1000);
234 }
235 }
236 return;
237 }
238
239 /* write something to a VGA attribute register */
240 static void
241 write_attr(u_int8_t index, u_int8_t data, u_int8_t videoOn)
242 {
243 u_int8_t v;
244
245 v = inb(0x3da); /* reset attr addr toggle */
246 if (videoOn)
247 outb(0x3c0, (index & 0x1F) | 0x20);
248 else
249 outb(0x3c0, (index & 0x1F));
250 outb(0x3c0, data);
251 }
252
253 static void
254 set_text_regs(void)
255 {
256 int i;
257
258 for (i = 0; i < SRREGS; i++) {
259 outb(VGA_SR_PORT, SR_regs[i].idx);
260 outb(VGA_SR_PORT + 1, SR_regs[i].val);
261 }
262 for (i = 0; i < CRREGS; i++) {
263 outb(VGA_CR_PORT, CR_regs[i].idx);
264 outb(VGA_CR_PORT + 1, CR_regs[i].val);
265 }
266 for (i = 0; i < GRREGS; i++) {
267 outb(VGA_GR_PORT, GR_regs[i].idx);
268 outb(VGA_GR_PORT + 1, GR_regs[i].val);
269 }
270
271 outb(0x3c2, 0x67); /* MISC */
272 outb(0x3c6, 0xff); /* MASK */
273
274 for (i = 0; i < 0x14; i++)
275 write_attr(i, vga_atc[i], 0);
276 write_attr(0x14, 0x00, 1); /* color select; video on */
277 }
278
279 static void
280 set_text_clut(int shift)
281 {
282 int i;
283
284 outb(0x3C6, 0xFF);
285 inb(0x3C7);
286 outb(0x3C8, 0);
287 inb(0x3C7);
288
289 for (i = 0; i < (16 * 3); ) {
290 outb(0x3c9, vga_dacpal[i++] << shift);
291 outb(0x3c9, vga_dacpal[i++] << shift);
292 outb(0x3c9, vga_dacpal[i++] << shift);
293 }
294 }
295
296 static void
297 load_font(u_int8_t *ISA_mem)
298 {
299 int i, j;
300 u_int8_t *font_page = (u_int8_t *)&ISA_mem[0xA0000];
301
302 outb(0x3C2, 0x67);
303 inb(0x3DA); /* Reset Attr toggle */
304
305 outb(0x3C0, 0x30);
306 outb(0x3C0, 0x01); /* graphics mode */
307 outw(0x3C4, 0x0001); /* reset sequencer */
308 outw(0x3C4, 0x0204); /* write to plane 2 */
309 outw(0x3C4, 0x0406); /* enable plane graphics */
310 outw(0x3C4, 0x0003); /* reset sequencer */
311 outw(0x3CE, 0x0402); /* read plane 2 */
312 outw(0x3CE, 0x0500); /* write mode 0, read mode 0 */
313 outw(0x3CE, 0x0605); /* set graphics mode */
314
315 for (i = 0; i < sizeof(font); i += 16) {
316 for (j = 0; j < 16; j++) {
317 __asm__ volatile("eieio");
318 font_page[(2*i)+j] = font[i+j];
319 }
320 }
321 }
322
323 static void
324 unlock_S3(void)
325 {
326 int s3_devid;
327
328 outw(VGA_CR_PORT, 0x3848);
329 outw(VGA_CR_PORT, 0x39a5);
330 outb(VGA_CR_PORT, 0x2d);
331 s3_devid = inb(VGA_CR_DATA) << 8;
332 outb(VGA_CR_PORT, 0x2e);
333 s3_devid |= inb(VGA_CR_DATA);
334
335 if (s3_devid != 0x8812) {
336 /* from the S3 manual */
337 outb(0x46E8, 0x10); /* Put into setup mode */
338 outb(0x3C3, 0x10);
339 outb(0x102, 0x01); /* Enable registers */
340 outb(0x46E8, 0x08); /* Enable video */
341 outb(0x3C3, 0x08);
342 outb(0x4AE8, 0x00);
343 outb(VGA_CR_PORT, 0x38); /* Unlock all registers */
344 outb(VGA_CR_DATA, 0x48);
345 outb(VGA_CR_PORT, 0x39);
346 outb(VGA_CR_DATA, 0xA5);
347 outb(VGA_CR_PORT, 0x40);
348 outb(VGA_CR_DATA, inb(0x3D5)|0x01);
349 outb(VGA_CR_PORT, 0x33);
350 outb(VGA_CR_DATA, inb(0x3D5)&~0x52);
351 outb(VGA_CR_PORT, 0x35);
352 outb(VGA_CR_DATA, inb(0x3D5)&~0x30);
353 outb(VGA_CR_PORT, 0x3A);
354 outb(VGA_CR_DATA, 0x00);
355 outb(VGA_CR_PORT, 0x53);
356 outb(VGA_CR_DATA, 0x00);
357 outb(VGA_CR_PORT, 0x31);
358 outb(VGA_CR_DATA, inb(0x3D5)&~0x4B);
359 outb(VGA_CR_PORT, 0x58);
360
361 outb(VGA_CR_DATA, 0);
362
363 outb(VGA_CR_PORT, 0x54);
364 outb(VGA_CR_DATA, 0x38);
365 outb(VGA_CR_PORT, 0x60);
366 outb(VGA_CR_DATA, 0x07);
367 outb(VGA_CR_PORT, 0x61);
368 outb(VGA_CR_DATA, 0x80);
369 outb(VGA_CR_PORT, 0x62);
370 outb(VGA_CR_DATA, 0xA1);
371 outb(VGA_CR_PORT, 0x69); /* High order bits for cursor address */
372 outb(VGA_CR_DATA, 0);
373
374 outb(VGA_CR_PORT, 0x32);
375 outb(VGA_CR_DATA, inb(0x3D5)&~0x10);
376 } else {
377 /* IBM Portable 860 */
378 outw(VGA_SR_PORT, 0x0806);
379 outw(VGA_SR_PORT, 0x1041);
380 outw(VGA_SR_PORT, 0x1128);
381 outw(VGA_CR_PORT, 0x4000);
382 outw(VGA_CR_PORT, 0x3100);
383 outw(VGA_CR_PORT, 0x3a05);
384 outw(VGA_CR_PORT, 0x6688);
385 outw(VGA_CR_PORT, 0x5800); /* disable linear addressing */
386 outw(VGA_CR_PORT, 0x4500); /* disable H/W cursor */
387 outw(VGA_SR_PORT, 0x5410); /* enable auto-centering */
388 outw(VGA_SR_PORT, 0x561f);
389 outw(VGA_SR_PORT, 0x1b80); /* lock DCLK selection */
390 outw(VGA_CR_PORT, 0x3900); /* lock S3 registers */
391 outw(VGA_CR_PORT, 0x3800);
392 }
393 }
394
395 static void
396 clear_video_memory(void)
397 {
398 int i, j;
399
400 for (i = 0; i < LINES; i++) {
401 for (j = 0; j < COLS; j++) {
402 videomem[((i * COLS)+j) * 2] = 0x20; /* space */
403 videomem[((i * COLS)+j) * 2 + 1] = 0x07; /* fg/bg */
404 }
405 }
406 }
407
408 #endif /* VGA_RESET */
409