1/* Copyright (c) 2005 Advanced Micro Devices, Inc.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 *
21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
22 * contributors may be used to endorse or promote products derived from this
23 * software without specific prior written permission.
24 * */
25
26/*
27 * This file contains routines to set modes using the VGA registers.
28 * Since this file is for the first generation graphics unit, it interfaces
29 * to SoftVGA registers.  It works for both VSA1 and VSA2.
30 * */
31
32/* SoftVGA Extended CRTC register indices and bit definitions */
33
34#define CRTC_EXTENDED_REGISTER_LOCK		0x30
35#define CRTC_MODE_SWITCH_CONTROL		0x3F
36
37/* BIT DEFINITIONS */
38
39#define CRTC_BIT_16BPP					0x01
40#define CRTC_BIT_555					0x02
41
42/* LOCAL ROUTINE DEFINITIONS */
43
44int gu1_detect_vsa2(void);
45
46/*---------------------------------*/
47/*  MODE TABLES FOR VGA REGISTERS  */
48/*---------------------------------*/
49
50/* FOR SoftVGA, the CRTC_EXTENDED_ADDRESS_CONTROL (0x43) is always equal to
51 * 0x03 for a packed linear frame buffer organization.  The
52 * CRTC_EXTENDED_DAC_CONTROL (0x4B) is always equal to 0x03 to work with
53 * older versions of VSA1 (that needed to specify 8 or 16 bit bus to an
54 * external RAMDAC.  This is not used in VSA2.  The clock frequency is
55 * specified in register 0x4D if clock control (0x4C) is set to 0x80.
56 * Higher resolutions (1280x1024) use the CRTC_EXTENDED_VERTICAL_TIMING
57 * register (index 0x41).
58 */
59
60gfx_vga_struct gfx_vga_modes[] = {
61/*--------------------------------------------------------------------------*/
62    {
63     640, 480, 60,              /* 640x480                                                              */
64     25,                        /* 25 MHz clock = 60 Hz refresh rate    */
65     0xE3,                      /* miscOutput register                                  */
66     {
67      0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E,
68      /* standard CRTC                                                */
69      0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70      0xEA, 0x0C, 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3, 0xFF},
71     {
72      0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
73      /* extended CRTC                                                */
74      0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00}
75     },
76/*--------------------------------------------------------------------------*/
77    {
78     640, 480, 72,              /* 640x480 */
79     29,                        /* 29 MHz clock = 72 Hz refresh rate */
80     0xE3,                      /* miscOutput register */
81     {
82      0x63, 0x4f, 0x50, 0x86, 0x55, 0x99, 0x06, 0x3e,
83      /* standard CRTC */
84      0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85      0xe9, 0x0c, 0xdf, 0x00, 0x00, 0xe7, 0x00, 0xe3, 0xff},
86     {
87      0x6D, 0x00, 0x00, 0x03, 0x00, 0x01, 0x01, 0x00,
88      /* extended CRTC */
89      0x00, 0x00, 0x01, 0x08, 0x80, 0x1F, 0x00, 0x4B}
90     },
91/*--------------------------------------------------------------------------*/
92    {
93     640, 480, 75,              /* 640x480 */
94     31,
95     /* 31.5 MHz clock = 75 Hz refresh rate */
96     0xE3,                      /* miscOutput register */
97     {
98      0x64, 0x4F, 0x4F, 0x88, 0x54, 0x9B, 0xF2, 0x1F,
99      /* standard CRTC */
100      0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101      0xE1, 0x04, 0xDF, 0x50, 0x00, 0xDF, 0xF3, 0xE3, 0xFF},
102     {
103      0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
104      /* extended CRTC */
105      0x00, 0x00, 0x00, 0x03, 0x80, 0x1F, 0x00, 0x00}
106     },
107/*--------------------------------------------------------------------------*/
108    {
109     800, 600, 60,              /* 800x600 */
110     40,                        /* 40 MHz clock = 60 Hz refresh rate */
111     0x23,                      /* miscOutput register */
112     {
113      0x7F, 0x63, 0x64, 0x82, 0x6B, 0x1B, 0x72, 0xF0,
114      /* standard CRTC */
115      0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116      0x59, 0x0D, 0x57, 0x64, 0x00, 0x57, 0x73, 0xE3, 0xFF},
117     {
118      0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
119      /* extended CRTC */
120      0x00, 0x00, 0x00, 0x03, 0x80, 0x28, 0x00, 0x00}
121     },
122/*--------------------------------------------------------------------------*/
123    {
124     800, 600, 72,              /* 800x600 */
125     47,                        /* 47 MHz clock = 72 Hz refresh rate */
126     0x2B,                      /* miscOutput register */
127     {
128      0x7D, 0x63, 0x63, 0x81, 0x6D, 0x1B, 0x98, 0xF0,
129      /* standard CRTC */
130      0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131      0x7D, 0x03, 0x57, 0x00, 0x00, 0x57, 0x9A, 0xE3, 0xFF},
132     {
133      0x6F, 0x00, 0x00, 0x03, 0x00, 0x01, 0x01, 0x00,
134      /* extended CRTC */
135      0x00, 0x00, 0x01, 0x08, 0x80, 0x32, 0x00, 0x4B}
136     },
137/*--------------------------------------------------------------------------*/
138    {
139     800, 600, 75,              /* 800x600 */
140     49,
141     /* 49.5 MHz clock = 75 Hz refresh rate */
142     0x23,                      /* miscOutput register */
143     {
144      0x7F, 0x63, 0x63, 0x83, 0x68, 0x11, 0x6F, 0xF0,
145      /* standard CRTC */
146      0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147      0x59, 0x1C, 0x57, 0x64, 0x00, 0x57, 0x70, 0xE3, 0xFF},
148     {
149      0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
150      /* extended CRTC */
151      0x00, 0x00, 0x00, 0x03, 0x80, 0x31, 0x00, 0x00}
152     },
153/*--------------------------------------------------------------------------*/
154    {
155     1024, 768, 60,             /* 1024x768 */
156     65,                        /* 65 MHz clock = 60 Hz refresh rate */
157     0xE3,                      /* miscOutput register */
158     {
159      0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xF5,
160      /* standard CRTC */
161      0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162      0x04, 0x0A, 0xFF, 0x80, 0x00, 0xFF, 0x25, 0xE3, 0xFF},
163     {
164      0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
165      /* extended CRTC */
166      0x00, 0x00, 0x00, 0x03, 0x80, 0x41, 0x00, 0x00}
167     },
168/*--------------------------------------------------------------------------*/
169    {
170     1024, 768, 70,             /* 1024x768 */
171     76,                        /* 76 MHz clock = 70 Hz refresh rate */
172     0x2B,                      /* miscOutput register */
173     {
174      0xA1, 0x7F, 0x7F, 0x85, 0x85, 0x95, 0x24, 0xF5,
175      /* standard CRTC */
176      0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177      0x03, 0x09, 0xFF, 0x00, 0x00, 0xFF, 0x26, 0xE3, 0xFF},
178     {
179      0x62, 0x00, 0x00, 0x03, 0x00, 0x01, 0x01, 0x00,
180      /* extended CRTC */
181      0x00, 0x00, 0x01, 0x02, 0x80, 0x4B, 0x00, 0x4B}
182     },
183/*--------------------------------------------------------------------------*/
184    {
185     1024, 768, 75,             /* 1024x768 */
186     79,                        /* 79 MHz clock = 75 Hz refresh rate */
187     0xE3,                      /* miscOutput register */
188     {
189      0x9F, 0x7F, 0x7F, 0x83, 0x84, 0x8F, 0x1E, 0xF5,
190      /* standard CRTC */
191      0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192      0x01, 0x04, 0xFF, 0x80, 0x00, 0xFF, 0x1F, 0xE3, 0xFF},
193     {
194      0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
195      /* extended CRTC */
196      0x00, 0x00, 0x00, 0x03, 0x80, 0x4F, 0x00, 0x00}
197     },
198/*--------------------------------------------------------------------------*/
199    {
200     1280, 1024, 60,            /* 1280x1024 */
201     108,
202     /* 108 MHz clock = 60 Hz refresh rate */
203     0x23,                      /* miscOutput register */
204     {
205      0xCF, 0x9F, 0xA0, 0x92, 0xAA, 0x19, 0x28, 0x52,
206      /* standard CRTC */
207      0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208      0x01, 0x04, 0xFF, 0xA0, 0x00, 0x00, 0x29, 0xE3, 0xFF},
209     {
210      0x00, 0x51, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
211      /* extended CRTC */
212      0x00, 0x00, 0x00, 0x03, 0x80, 0x6C, 0x00, 0x00}
213     },
214/*--------------------------------------------------------------------------*/
215    {
216     1280, 1024, 75,            /* 1280x1024 */
217     135,
218     /* 135 MHz clock = 75 Hz refresh rate */
219     0x23,                      /* miscOutput register */
220     {
221      0xCE, 0x9F, 0x9F, 0x92, 0xA4, 0x15, 0x28, 0x52,
222      /* standard CRTC */
223      0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224      0x01, 0x04, 0xFF, 0xA0, 0x00, 0x00, 0x29, 0xE3, 0xFF},
225     {
226      0x00, 0x51, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
227      /* extended CRTC */
228      0x00, 0x00, 0x00, 0x03, 0x80, 0x87, 0x00, 0x00}
229     },
230/*--------------------------------------------------------------------------*/
231    {
232     1280, 1024, 85,            /* 1280x1024 */
233     159,
234     /* 159 MHz clock = 85 Hz refresh rate */
235     0x2B,                      /* miscOutput register */
236     {
237      0xD3, 0x9F, 0xA0, 0x98, 0xA8, 0x9C, 0x2E, 0x5A,
238      /* standard CRTC */
239      0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240      0x01, 0x04, 0xFF, 0x00, 0x00, 0xFF, 0x30, 0xE3, 0xFF},
241     {
242      0x6B, 0x41, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00,
243      /* extended CRTC */
244      0x00, 0x00, 0x01, 0x00, 0x80, 0x9D, 0x00, 0x4B}
245     },
246/*--------------------------------------------------------------------------*/
247};
248
249#define GFX_VGA_MODES sizeof(gfx_vga_modes)/sizeof(gfx_vga_struct)
250
251/*----------------------------------------------------------------------------
252 * gfx_get_softvga_active
253 *
254 * This returns the active status of SoftVGA
255 *----------------------------------------------------------------------------
256 */
257int
258gfx_get_softvga_active(void)
259{
260    unsigned short crtcindex, crtcdata;
261
262    if (gu1_detect_vsa2())
263        return (gfx_get_vsa2_softvga_enable());
264
265    crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
266    crtcdata = crtcindex + 1;
267
268    OUTB(crtcindex, CRTC_MODE_SWITCH_CONTROL);
269    return (INB(crtcdata) & 0x1);
270}
271
272/*----------------------------------------------------------------------------
273 * gfx_vga_test_pci
274 *
275 * This routine looks for the VGA PCI header.  It checks to see that bit 1
276 * of the command register is writable to know that SoftVGA is trapping
277 * the PCI config cuscles.  If SoftVGA is not emulating the header, the
278 * hardware will still respond with the proper device ID, etc.
279 *
280 * We need to know that SoftVGA is really there so that we can set the
281 * command register and have the proper effect (enable trapping of VGA).
282 * Otherwise, if we enable VGA via the PCI header, trapping really won't be
283 * enabled and the VGA register writes will go out to the external card.
284 *----------------------------------------------------------------------------
285 */
286int
287gfx_vga_test_pci(void)
288{
289    int softvga = 1;
290    unsigned long value;
291
292    value = gfx_pci_config_read(0x80009400);
293    if ((value & 0x0000FFFF) != 0x1078)
294        softvga = 0;
295    else {
296        value = gfx_pci_config_read(0x80009404);
297        gfx_pci_config_write(0x80009404, value | 0x02);
298        if (!(gfx_pci_config_read(0x80009404) & 0x02))
299            softvga = 0;
300        gfx_pci_config_write(0x80009404, value);
301    }
302    return (softvga);
303}
304
305/*----------------------------------------------------------------------------
306 * gfx_vga_get_pci_command
307 *
308 * This routine returns the value of the PCI command register.
309 *----------------------------------------------------------------------------
310 */
311unsigned char
312gfx_vga_get_pci_command(void)
313{
314    unsigned long value;
315
316    value = gfx_pci_config_read(0x80009404);
317    return ((unsigned char) value);
318}
319
320/*----------------------------------------------------------------------------
321 * gfx_vga_set_pci_command
322 *
323 * This routine writes the value of the PCI command register.  It is used
324 * to enable or disable SoftVGA.
325 *
326 *    Bit 0: Enable VGA IO
327 *    Bit 1: Enable VGA memory
328 *----------------------------------------------------------------------------
329 */
330int
331gfx_vga_set_pci_command(unsigned char command)
332{
333    unsigned long value;
334
335    value = gfx_pci_config_read(0x80009404) & 0xFFFFFF00;
336    value |= (unsigned long) command;
337    gfx_pci_config_write(0x80009404, value);
338    return (GFX_STATUS_OK);
339}
340
341/*----------------------------------------------------------------------------
342 * gfx_vga_seq_reset
343 *
344 * This routine enables or disables SoftVGA.  It is used to make SoftVGA
345 * "be quiet" and not interfere with any of the direct hardware access from
346 * Durango.  For VSA1, the sequencer is reset to stop text redraws.  VSA2 may
347 * provide a better way to have SoftVGA sit in the background.
348 *----------------------------------------------------------------------------
349 */
350int
351gfx_vga_seq_reset(int reset)
352{
353    OUTB(0x3C4, 0);
354    OUTB(0x3C5, (unsigned char) (reset ? 0x00 : 0x03));
355    return (GFX_STATUS_OK);
356}
357
358/*----------------------------------------------------------------------------
359 * gfx_vga_set_graphics_bits
360 *
361 * This routine sets the standard VGA sequencer, graphics controller, and
362 * attribute registers to appropriate values for a graphics mode (packed,
363 * 8 BPP or greater).  This is also known as "VESA" modes.  The timings for
364 * a particular mode are handled by the CRTC registers, which are set by
365 * the "gfx_vga_restore" routine.   Most OSs that use VGA to set modes save
366 * and restore the standard VGA registers themselves, which is why these
367 * registers are not part of the save/restore paradigm.
368 *----------------------------------------------------------------------------
369 */
370int
371gfx_vga_set_graphics_bits(void)
372{
373    /* SET GRAPHICS BIT IN GRAPHICS CONTROLLER REG 0x06 */
374
375    OUTB(0x3CE, 0x06);
376    OUTB(0x3CF, 0x01);
377
378    /* SET GRAPHICS BIT IN ATTRIBUTE CONTROLLER REG 0x10 */
379
380    INB(0x3BA);                 /* Reset flip-flop */
381    INB(0x3DA);
382    OUTB(0x3C0, 0x10);
383    OUTB(0x3C0, 0x01);
384    return (GFX_STATUS_OK);
385}
386
387/*----------------------------------------------------------------------------
388 * gfx_vga_mode
389 *
390 * This routine searches the VGA mode table for a match of the specified
391 * mode and then fills in the VGA structure with the associated VGA register
392 * values.  The "gfx_vga_restore" routine can then be called to actually
393 * set the mode.
394 *----------------------------------------------------------------------------
395 */
396int
397gfx_vga_mode(gfx_vga_struct * vga, int xres, int yres, int bpp, int hz)
398{
399    unsigned int i;
400    unsigned short pitch;
401
402    for (i = 0; i < GFX_VGA_MODES; i++) {
403        if ((gfx_vga_modes[i].xsize == xres) &&
404            (gfx_vga_modes[i].ysize == yres) && (gfx_vga_modes[i].hz == hz)) {
405            /* COPY ENTIRE STRUCTURE FROM THE TABLE */
406
407            *vga = gfx_vga_modes[i];
408
409            /* SET PITCH TO 1K OR 2K */
410            /* CRTC_EXTENDED_OFFSET index is 0x45, so offset = 0x05 */
411
412            pitch = (unsigned short) xres;
413            if (bpp > 8)
414                pitch <<= 1;
415            if (pitch <= 1024)
416                pitch = 1024 >> 3;
417            else
418                pitch = 2048 >> 3;
419            vga->stdCRTCregs[0x13] = (unsigned char) pitch;
420            vga->extCRTCregs[0x05] = (unsigned char) ((pitch >> 8) & 0x03);
421
422            /* SET PROPER COLOR DEPTH VALUE */
423            /* CRTC_EXTENDED_COLOR_CONTROL index is 0x46, so offset = 0x06 */
424
425            switch (bpp) {
426            case 15:
427                vga->extCRTCregs[0x06] = CRTC_BIT_16BPP | CRTC_BIT_555;
428                break;
429            case 16:
430                vga->extCRTCregs[0x06] = CRTC_BIT_16BPP;
431                break;
432            default:
433                vga->extCRTCregs[0x06] = 0;
434                break;
435            }
436            return (GFX_STATUS_OK);
437        }
438    }
439    return (GFX_STATUS_UNSUPPORTED);
440}
441
442/*----------------------------------------------------------------------------
443 * gfx_vga_pitch
444 *
445 * This routine updates the VGA regisers in the specified VGA structure for
446 * the specified pitch.  It does not program the hardware.
447 *----------------------------------------------------------------------------
448 */
449int
450gfx_vga_pitch(gfx_vga_struct * vga, unsigned short pitch)
451{
452    pitch >>= 3;
453    vga->stdCRTCregs[0x13] = (unsigned char) pitch;
454    vga->extCRTCregs[0x05] = (unsigned char) ((pitch >> 8) & 0x03);
455    return (0);
456}
457
458/*----------------------------------------------------------------------------
459 * gfx_vga_save
460 *
461 * This routine saves the state of the VGA registers into the specified
462 * structure.  Flags indicate what portions of the register state need to
463 * be saved.
464 *----------------------------------------------------------------------------
465 */
466int
467gfx_vga_save(gfx_vga_struct * vga, int flags)
468{
469    int i;
470    unsigned short crtcindex, crtcdata;
471
472    crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
473    crtcdata = crtcindex + 1;
474
475    /* CHECK MISCELLANEOUS OUTPUT FLAG */
476
477    if (flags & GFX_VGA_FLAG_MISC_OUTPUT) {
478        /* SAVE MISCCELLANEOUS OUTPUT REGISTER */
479
480        vga->miscOutput = INB(0x3CC);
481    }
482
483    /* CHECK STANDARD CRTC FLAG */
484
485    if (flags & GFX_VGA_FLAG_STD_CRTC) {
486        /* SAVE STANDARD CRTC REGISTERS */
487
488        for (i = 0; i < GFX_STD_CRTC_REGS; i++) {
489            OUTB(crtcindex, (unsigned char) i);
490            vga->stdCRTCregs[i] = INB(crtcdata);
491        }
492    }
493
494    /* CHECK EXTENDED CRTC FLAG */
495
496    if (flags & GFX_VGA_FLAG_EXT_CRTC) {
497        /* SAVE EXTENDED CRTC REGISTERS */
498
499        for (i = 0; i < GFX_EXT_CRTC_REGS; i++) {
500            OUTB(crtcindex, (unsigned char) (0x40 + i));
501            vga->extCRTCregs[i] = INB(crtcdata);
502        }
503    }
504    return (0);
505}
506
507/*----------------------------------------------------------------------------
508 * gfx_vga_clear_extended
509 *
510 * This routine clears the extended SoftVGA register values to have SoftVGA
511 * behave like standard VGA.
512 *----------------------------------------------------------------------------
513 */
514void
515gfx_vga_clear_extended(void)
516{
517    int i;
518    unsigned short crtcindex, crtcdata;
519
520    crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
521    crtcdata = crtcindex + 1;
522
523    OUTB(crtcindex, 0x30);
524    OUTB(crtcdata, 0x57);
525    OUTB(crtcdata, 0x4C);
526    for (i = 0x40; i <= 0x4F; i++) {
527        OUTB(crtcindex, (unsigned char) i);
528        OUTB(crtcdata, 0);
529    }
530    OUTB(crtcindex, 0x30);
531    OUTB(crtcdata, 0x00);
532}
533
534/*----------------------------------------------------------------------------
535 * gfx_vga_restore
536 *
537 * This routine restores the state of the VGA registers from the specified
538 * structure.  Flags indicate what portions of the register state need to
539 * be saved.
540 *----------------------------------------------------------------------------
541 */
542int
543gfx_vga_restore(gfx_vga_struct * vga, int flags)
544{
545    int i;
546    unsigned short crtcindex, crtcdata;
547
548    crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
549    crtcdata = crtcindex + 1;
550
551    /* CHECK MISCELLANEOUS OUTPUT FLAG */
552
553    if (flags & GFX_VGA_FLAG_MISC_OUTPUT) {
554        /* RESTORE MISCELLANEOUS OUTPUT REGISTER VALUE */
555
556        OUTB(0x3C2, vga->miscOutput);
557    }
558
559    /* CHECK STANDARD CRTC FLAG */
560
561    if (flags & GFX_VGA_FLAG_STD_CRTC) {
562        /* UNLOCK STANDARD CRTC REGISTERS */
563
564        OUTB(crtcindex, 0x11);
565        OUTB(crtcdata, 0);
566
567        /* RESTORE STANDARD CRTC REGISTERS */
568
569        for (i = 0; i < GFX_STD_CRTC_REGS; i++) {
570            OUTB(crtcindex, (unsigned char) i);
571            OUTB(crtcdata, vga->stdCRTCregs[i]);
572        }
573    }
574
575    /* CHECK EXTENDED CRTC FLAG */
576
577    if (flags & GFX_VGA_FLAG_EXT_CRTC) {
578        /* UNLOCK EXTENDED CRTC REGISTERS */
579
580        OUTB(crtcindex, 0x30);
581        OUTB(crtcdata, 0x57);
582        OUTB(crtcdata, 0x4C);
583
584        /* RESTORE EXTENDED CRTC REGISTERS */
585
586        for (i = 0; i < GFX_EXT_CRTC_REGS; i++) {
587            OUTB(crtcindex, (unsigned char) (0x40 + i));
588            OUTB(crtcdata, vga->extCRTCregs[i]);
589        }
590
591        /* LOCK EXTENDED CRTC REGISTERS */
592
593        OUTB(crtcindex, 0x30);
594        OUTB(crtcdata, 0x00);
595
596        /* CHECK IF DIRECT FRAME BUFFER MODE (VESA MODE) */
597
598        if (vga->extCRTCregs[0x03] & 1) {
599            /* SET BORDER COLOR TO BLACK */
600            /* This really should be another thing saved/restored, but */
601            /* Durango currently doesn't do the attr controller registers. */
602
603            INB(0x3BA);         /* Reset flip-flop */
604            INB(0x3DA);
605            OUTB(0x3C0, 0x11);
606            OUTB(0x3C0, 0x00);
607        }
608    }
609    return (0);
610}
611
612/*----------------------------------------------------------------------------
613 * gfx_vga_mode_switch
614 *
615 * This routine programs the SoftVGA register to indicate that a mode switch
616 * is in progress.  This results in a cleaner mode switch since SoftVGA will
617 * not validate the hardware with intermediate values.
618 *----------------------------------------------------------------------------
619 */
620int
621gfx_vga_mode_switch(int active)
622{
623    unsigned short crtcindex, crtcdata;
624
625    crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
626    crtcdata = crtcindex + 1;
627
628    /* UNLOCK EXTENDED CRTC REGISTERS */
629
630    OUTB(crtcindex, CRTC_EXTENDED_REGISTER_LOCK);
631    OUTB(crtcdata, 0x57);
632    OUTB(crtcdata, 0x4C);
633
634    /* SIGNAL THE BEGINNING OR END OF THE MODE SWITCH */
635    /* SoftVGA will hold off validating the back end hardware. */
636
637    OUTB(crtcindex, CRTC_MODE_SWITCH_CONTROL);
638    active = active ? 1 : 0;
639    OUTB(crtcdata, (unsigned char) active);
640
641    /* WAIT UNTIL SOFTVGA HAS VALIDATED MODE IF ENDING MODE SWITCH */
642    /* This is for VSA1 only, where SoftVGA waits until the next */
643    /* vertical blank to validate the hardware state. */
644
645    if ((!active) && (!(gu1_detect_vsa2()))) {
646        OUTB(crtcindex, 0x33);
647        while (INB(crtcdata) & 0x80);
648    }
649
650    /* LOCK EXTENDED CRTC REGISTERS */
651
652    OUTB(crtcindex, CRTC_EXTENDED_REGISTER_LOCK);
653    OUTB(crtcdata, 0x00);
654    return (0);
655}
656
657/*----------------------------------------------------------------------------
658 * gu1_detect_vsa2
659 *
660 * This routine detects if VSA2 is present.  The interface to SoftVGA
661 * changed slightly.
662 *----------------------------------------------------------------------------
663 */
664int
665gu1_detect_vsa2(void)
666{
667    unsigned short crtcindex, crtcdata;
668
669    crtcindex = (INB(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
670    crtcdata = crtcindex + 1;
671    OUTB(crtcindex, 0x35);
672    if (INB(crtcdata) != 'C')
673        return (0);
674    OUTB(crtcindex, 0x36);
675    if (INB(crtcdata) != 'X')
676        return (0);
677    return (1);
678}
679
680/* END OF FILE */
681