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