1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/nsc_gx2_vga.c,v 1.2tsi Exp $ */
2/*
3 * $Workfile: nsc_gx2_vga.c $
4 * $Revision: 1.1.1.1 $
5 * $Author: mrg $
6 *
7 * This file contains routines to set modes using the VGA registers.
8 * Since this file is for the first generation graphics unit, it interfaces
9 * to SoftVGA registers.  It works for both VSA1 and VSA2.
10 *
11 * NSC_LIC_ALTERNATIVE_PREAMBLE
12 *
13 * Revision 1.0
14 *
15 * National Semiconductor Alternative GPL-BSD License
16 *
17 * National Semiconductor Corporation licenses this software
18 * ("Software"):
19 *
20 *      nsc XFree86
21 *
22 * under one of the two following licenses, depending on how the
23 * Software is received by the Licensee.
24 *
25 * If this Software is received as part of the Linux Framebuffer or
26 * other GPL licensed software, then the GPL license designated
27 * NSC_LIC_GPL applies to this Software; in all other circumstances
28 * then the BSD-style license designated NSC_LIC_BSD shall apply.
29 *
30 * END_NSC_LIC_ALTERNATIVE_PREAMBLE */
31
32/* NSC_LIC_BSD
33 *
34 * National Semiconductor Corporation Open Source License for Durango
35 *
36 * (BSD License with Export Notice)
37 *
38 * Copyright (c) 1999-2001
39 * National Semiconductor Corporation.
40 * All rights reserved.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 *
46 *   * Redistributions of source code must retain the above copyright
47 *     notice, this list of conditions and the following disclaimer.
48 *
49 *   * Redistributions in binary form must reproduce the above
50 *     copyright notice, this list of conditions and the following
51 *     disclaimer in the documentation and/or other materials provided
52 *     with the distribution.
53 *
54 *   * Neither the name of the National Semiconductor Corporation nor
55 *     the names of its contributors may be used to endorse or promote
56 *     products derived from this software without specific prior
57 *     written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
60 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
61 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
62 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
63 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
64 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
66 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
67 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
68 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
69 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
71 * OF SUCH DAMAGE.
72 *
73 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
74 * YOUR JURISDICTION. It is licensee's responsibility to comply with
75 * any export regulations applicable in licensee's jurisdiction. Under
76 * CURRENT (2001) U.S. export regulations this software
77 * is eligible for export from the U.S. and can be downloaded by or
78 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
79 * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
80 * Syria, Sudan, Afghanistan and any other country to which the U.S.
81 * has embargoed goods and services.
82 *
83 * END_NSC_LIC_BSD */
84
85/* NSC_LIC_GPL
86 *
87 * National Semiconductor Corporation Gnu General Public License for Durango
88 *
89 * (GPL License with Export Notice)
90 *
91 * Copyright (c) 1999-2001
92 * National Semiconductor Corporation.
93 * All rights reserved.
94 *
95 * Redistribution and use in source and binary forms, with or without
96 * modification, are permitted under the terms of the GNU General
97 * Public License as published by the Free Software Foundation; either
98 * version 2 of the License, or (at your option) any later version
99 *
100 * In addition to the terms of the GNU General Public License, neither
101 * the name of the National Semiconductor Corporation nor the names of
102 * its contributors may be used to endorse or promote products derived
103 * from this software without specific prior written permission.
104 *
105 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
106 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
107 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
108 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
109 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY
110 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
111 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
112 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
113 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
114 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE,
115 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY
116 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
117 * OF SUCH DAMAGE. See the GNU General Public License for more details.
118 *
119 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
120 * YOUR JURISDICTION. It is licensee's responsibility to comply with
121 * any export regulations applicable in licensee's jurisdiction. Under
122 * CURRENT (2001) U.S. export regulations this software
123 * is eligible for export from the U.S. and can be downloaded by or
124 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed
125 * destinations which include Cuba, Iraq, Libya, North Korea, Iran,
126 * Syria, Sudan, Afghanistan and any other country to which the U.S.
127 * has embargoed goods and services.
128 *
129 * You should have received a copy of the GNU General Public License
130 * along with this file; if not, write to the Free Software Foundation,
131 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
132 *
133 * END_NSC_LIC_GPL */
134
135#ifdef HAVE_CONFIG_H
136#include "config.h"
137#endif
138
139/* VGA STRUCTURE */
140
141#define GU2_STD_CRTC_REGS 25
142#define GU2_EXT_CRTC_REGS 15
143#define GU2_GDC_REGS 9
144#define GU2_SEQ_REGS 5
145
146#define GU2_VGA_FLAG_MISC_OUTPUT	0x1
147#define GU2_VGA_FLAG_STD_CRTC		0x2
148#define GU2_VGA_FLAG_EXT_CRTC		0x4
149#define GU2_VGA_FLAG_GDC		0x10
150#define GU2_VGA_FLAG_SEQ		0x20
151#define GU2_VGA_FLAG_PALETTE 	0x40
152#define GU2_VGA_FLAG_ATTR 	0x80
153
154static unsigned int GDCregs[10];
155static unsigned int SEQregs[10];
156static unsigned int palette[256];
157static unsigned int ATTRregs[32];
158static unsigned char *font_data = NULL;
159
160#define VGA_BLOCK 0x40000		/* 256 k */
161
162void gu2_vga_extcrtc(char offset, int reset);
163int gu2_get_vga_active(void);
164void gu2_vga_font_data(int flag);
165void gu2_set_vga(int reset);
166int gu2_vga_seq_blanking(void);
167int gu2_vga_attr_ctrl(int reset);
168void gu2_vga_to_gfx(void);
169void gu2_gfx_to_vga(int vga_mode);
170int gu2_vga_seq_reset(int reset);
171int gu2_vga_save(gfx_vga_struct * vga, int flags);
172void gu2_vga_clear_extended(void);
173int gu2_vga_restore(gfx_vga_struct * vga, int flags);
174
175int
176gu2_get_vga_active(void)
177{
178   int data = gfx_read_reg32(MDC_GENERAL_CFG);
179
180   if (data & MDC_GCFG_VGAE)
181      return 1;
182   return 0;
183}
184
185void
186gu2_vga_font_data(int flag)
187{
188   if (flag == 0) {
189      if (font_data == NULL) {
190	 font_data = malloc(VGA_BLOCK);
191      }
192      DEBUGMSG(1, (0, X_NONE, "Saving VGA Data\n"));
193      memcpy(font_data, gfx_virt_fbptr, VGA_BLOCK);
194   } else {
195      if (font_data) {
196	 DEBUGMSG(1, (0, X_NONE, "Restore VGA Data\n"));
197	 memcpy(gfx_virt_fbptr, font_data, VGA_BLOCK);
198	 free(font_data);
199	 font_data = NULL;
200      }
201   }
202}
203
204void
205gu2_set_vga(int reset)
206{
207   int data = gfx_read_reg32(MDC_GENERAL_CFG);
208
209   if (reset)
210      data |= MDC_GCFG_VGAE;
211   else
212      data &= ~MDC_GCFG_VGAE;
213   gfx_write_reg32(MDC_GENERAL_CFG, data);
214}
215
216int
217gu2_vga_seq_blanking(void)
218{
219   int tmp;
220
221   gfx_outb(0x3C4, 1);
222   tmp = gfx_inb(0x3C5);
223   tmp |= 0x20;
224   tmp |= tmp << 8;
225   gfx_outw(0x3C4, tmp);
226
227   gfx_delay_milliseconds(1);
228   return (GFX_STATUS_OK);
229}
230
231int
232gu2_vga_attr_ctrl(int reset)
233{
234   (void) gfx_inb(0x3DA);
235   gfx_outb(0x3C0, (unsigned char)(reset ? 0x00 : 0x20));
236   if (reset)
237      (void) gfx_inb(0x3DA);
238   return (GFX_STATUS_OK);
239}
240
241void
242gu2_vga_to_gfx(void)
243{
244   gu2_vga_attr_ctrl(0);
245
246   gu2_vga_seq_blanking();
247   gfx_delay_milliseconds(2);
248
249   gu2_vga_extcrtc(0x3F, 1);
250}
251
252void
253gu2_gfx_to_vga(int vga_mode)
254{
255   char sequencer;
256
257   gu2_vga_extcrtc(0x40, vga_mode);
258
259   /* clear the display blanking bit */
260   gfx_outb(MDC_SEQUENCER_INDEX, MDC_SEQUENCER_CLK_MODE);
261   sequencer = gfx_inb(MDC_SEQUENCER_DATA);
262   sequencer &= ~MDC_CLK_MODE_SCREEN_OFF;
263   sequencer |= 1;
264   gfx_outb(MDC_SEQUENCER_DATA, sequencer);
265
266   gfx_delay_milliseconds(1);
267
268   /*restart the sequencer */
269   gfx_outw(0x3C4, 0x300);
270
271   /* turn on the attribute controler */
272   (void) gfx_inb(0x3DA);
273   gfx_outb(0x3C0, 0x20);
274   (void) gfx_inb(0x3DA);
275
276   gu2_vga_extcrtc(0x3F, 0);
277}
278
279/*-----------------------------------------------------------------------------
280 * gfx_vga_seq_reset
281 *
282 * This routine enables or disables SoftVGA.  It is used to make SoftVGA
283 * "be quiet" and not interfere with any of the direct hardware access from
284 * Durango.  For VSA1, the sequencer is reset to stop text redraws.  VSA2 may
285 * provide a better way to have SoftVGA sit in the background.
286 *-----------------------------------------------------------------------------
287 */
288int
289gu2_vga_seq_reset(int reset)
290{
291   gfx_outb(0x3C4, 0);
292   gfx_outb(0x3C5, (unsigned char)(reset ? 0x00 : 0x03));
293   return (GFX_STATUS_OK);
294}
295
296/*-----------------------------------------------------------------------------
297 * gfx_vga_save
298 *
299 * This routine saves the state of the VGA registers into the specified
300 * structure.  Flags indicate what portions of the register state need to
301 * be saved.
302 *-----------------------------------------------------------------------------
303 */
304int
305gu2_vga_save(gfx_vga_struct * vga, int flags)
306{
307   int i;
308   unsigned short crtcindex, crtcdata;
309
310   crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
311   crtcdata = crtcindex + 1;
312
313   /* CHECK MISCELLANEOUS OUTPUT FLAG */
314
315   if (flags & GU2_VGA_FLAG_MISC_OUTPUT) {
316      /* SAVE MISCCELLANEOUS OUTPUT REGISTER */
317
318      vga->miscOutput = gfx_inb(0x3CC);
319   }
320
321   /* CHECK SEQ */
322
323   if (flags & GU2_VGA_FLAG_SEQ) {
324      /* SAVE STANDARD CRTC REGISTERS */
325
326      for (i = 1; i < GU2_SEQ_REGS; i++) {
327	 gfx_outb(0x3C4, (unsigned char)i);
328	 SEQregs[i] = gfx_inb(0x3C5);
329      }
330   }
331
332   /* CHECK STANDARD CRTC FLAG */
333
334   if (flags & GU2_VGA_FLAG_STD_CRTC) {
335      /* SAVE STANDARD CRTC REGISTERS */
336
337      for (i = 0; i < GU2_STD_CRTC_REGS; i++) {
338	 gfx_outb(crtcindex, (unsigned char)i);
339	 vga->stdCRTCregs[i] = gfx_inb(crtcdata);
340      }
341   }
342
343   /* CHECK GDC */
344
345   if (flags & GU2_VGA_FLAG_GDC) {
346      /* SAVE STANDARD CRTC REGISTERS */
347
348      for (i = 0; i < GU2_GDC_REGS; i++) {
349	 gfx_outb(0x3CE, (unsigned char)i);
350	 GDCregs[i] = gfx_inb(0x3CF);
351      }
352   }
353
354   /* CHECK EXTENDED CRTC FLAG */
355
356   if (flags & GU2_VGA_FLAG_EXT_CRTC) {
357      /* SAVE EXTENDED CRTC REGISTERS */
358
359      for (i = 0; i < GU2_EXT_CRTC_REGS; i++) {
360	 gfx_outb(crtcindex, (unsigned char)(0x40 + i));
361	 vga->extCRTCregs[i] = gfx_inb(crtcdata);
362      }
363   }
364
365   if (flags & GU2_VGA_FLAG_PALETTE) {
366      /* SAVE PALETTE DATA */
367
368      for (i = 0; i < 0x100; i++) {
369	 gfx_outb(0x3C7, i);
370	 palette[i] = gfx_inb(0x3C9);
371      }
372   }
373
374   if (flags & GU2_VGA_FLAG_ATTR) {
375      /* SAVE Attribute  DATA */
376
377      for (i = 0; i < 21; i++) {
378	 gfx_inb(0x3DA);
379	 gfx_outb(0x3C0, i);
380	 ATTRregs[i] = gfx_inb(0x3C1);
381      }
382   }
383   /* save the VGA data */
384   gu2_vga_font_data(0);
385   return (0);
386}
387
388/*-----------------------------------------------------------------------------
389 * gfx_vga_clear_extended
390 *
391 * This routine clears the extended SoftVGA register values to have SoftVGA
392 * behave like standard VGA.
393 *-----------------------------------------------------------------------------
394 */
395void
396gu2_vga_clear_extended(void)
397{
398   int i;
399   unsigned short crtcindex, crtcdata;
400
401   crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
402   crtcdata = crtcindex + 1;
403
404   gfx_outb(crtcindex, 0x30);
405   gfx_outb(crtcdata, 0x57);
406   gfx_outb(crtcdata, 0x4C);
407   for (i = 0x41; i <= 0x4F; i++) {
408      gfx_outb(crtcindex, (unsigned char)i);
409      gfx_outb(crtcdata, 0);
410   }
411   gfx_outb(crtcindex, 0x30);
412   gfx_outb(crtcdata, 0x00);
413}
414
415void
416gu2_vga_extcrtc(char offset, int reset)
417{
418   unsigned short crtcindex, crtcdata;
419
420   crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
421   crtcdata = crtcindex + 1;
422
423   /* UNLOCK EXTENDED CRTC REGISTERS */
424
425   gfx_outb(crtcindex, 0x30);
426   gfx_outb(crtcdata, 0x57);
427   gfx_outb(crtcdata, 0x4C);
428
429   /* RESTORE EXTENDED CRTC REGISTERS */
430
431   gfx_outb(crtcindex, offset);
432   gfx_outb(crtcdata, reset);
433
434#if 0
435   /* LOCK EXTENDED CRTC REGISTERS */
436
437   gfx_outb(crtcindex, 0x30);
438   gfx_outb(crtcdata, 0x00);
439#endif
440}
441
442/*-----------------------------------------------------------------------------
443 * gfx_vga_restore
444 *
445 * This routine restores the state of the VGA registers from the specified
446 * structure.  Flags indicate what portions of the register state need to
447 * be saved.
448 *-----------------------------------------------------------------------------
449 */
450int
451gu2_vga_restore(gfx_vga_struct * vga, int flags)
452{
453   int i;
454   unsigned short crtcindex, crtcdata;
455
456   crtcindex = (gfx_inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
457   crtcdata = crtcindex + 1;
458
459   /* CHECK MISCELLANEOUS OUTPUT FLAG */
460
461   if (flags & GU2_VGA_FLAG_MISC_OUTPUT) {
462      /* RESTORE MISCELLANEOUS OUTPUT REGISTER VALUE */
463
464      gfx_outb(0x3C2, vga->miscOutput);
465   }
466
467   /* CHECK SEQ */
468
469   if (flags & GU2_VGA_FLAG_SEQ) {
470      /* RESTORE STANDARD CRTC REGISTERS */
471
472      for (i = 1; i < GU2_SEQ_REGS; i++) {
473	 gfx_outb(0x3C4, (unsigned char)i);
474	 gfx_outb(0x3C5, SEQregs[i]);
475      }
476   }
477
478   /* CHECK STANDARD CRTC FLAG */
479
480   if (flags & GU2_VGA_FLAG_STD_CRTC) {
481      /* UNLOCK STANDARD CRTC REGISTERS */
482
483      gfx_outb(crtcindex, 0x11);
484      gfx_outb(crtcdata, 0);
485
486      /* RESTORE STANDARD CRTC REGISTERS */
487
488      for (i = 0; i < GU2_STD_CRTC_REGS; i++) {
489	 gfx_outb(crtcindex, (unsigned char)i);
490	 gfx_outb(crtcdata, vga->stdCRTCregs[i]);
491      }
492   }
493
494   /* CHECK GDC */
495
496   if (flags & GU2_VGA_FLAG_GDC) {
497      /* SAVE STANDARD CRTC REGISTERS */
498
499      for (i = 0; i < GU2_GDC_REGS; i++) {
500	 gfx_outb(0x3CE, (unsigned char)i);
501	 gfx_outb(0x3CF, GDCregs[i]);
502      }
503   }
504
505   /* CHECK EXTENDED CRTC FLAG */
506
507   if (flags & GU2_VGA_FLAG_EXT_CRTC) {
508      /* UNLOCK EXTENDED CRTC REGISTERS */
509
510      gfx_outb(crtcindex, 0x30);
511      gfx_outb(crtcdata, 0x57);
512      gfx_outb(crtcdata, 0x4C);
513
514      /* RESTORE EXTENDED CRTC REGISTERS */
515
516      for (i = 1; i < GU2_EXT_CRTC_REGS; i++) {
517	 gfx_outb(crtcindex, (unsigned char)(0x40 + i));
518	 gfx_outb(crtcdata, vga->extCRTCregs[i]);
519      }
520
521      /* LOCK EXTENDED CRTC REGISTERS */
522
523      gfx_outb(crtcindex, 0x30);
524      gfx_outb(crtcdata, 0x00);
525
526      /* CHECK IF DIRECT FRAME BUFFER MODE (VESA MODE) */
527
528      if (vga->extCRTCregs[0x03] & 1) {
529	 /* SET BORDER COLOR TO BLACK */
530	 /* This really should be another thing saved/restored, but */
531	 /* Durango currently doesn't do the attr controller registers. */
532
533	 gfx_inb(0x3BA);		/* Reset flip-flop */
534	 gfx_inb(0x3DA);
535	 gfx_outb(0x3C0, 0x11);
536	 gfx_outb(0x3C0, 0x00);
537      }
538   }
539
540   if (flags & GU2_VGA_FLAG_PALETTE) {
541      /* RESTORE PALETTE DATA */
542
543      for (i = 0; i < 0x100; i++) {
544	 gfx_outb(0x3C8, i);
545	 gfx_outb(0x3C9, palette[i]);
546      }
547   }
548
549   if (flags & GU2_VGA_FLAG_ATTR) {
550      /* RESTORE Attribute  DATA */
551
552      for (i = 0; i < 21; i++) {
553	 gfx_inb(0x3DA);
554	 gfx_outb(0x3C0, i);
555	 gfx_outb(0x3C0, ATTRregs[i]);
556      }
557      /* SAVE Attribute  DATA */
558
559      for (i = 0; i < 21; i++) {
560	 gfx_inb(0x3DA);
561	 gfx_outb(0x3C0, i);
562      }
563   }
564
565   /* restore the VGA data */
566   gu2_vga_font_data(1);
567
568   return (0);
569}
570
571/* END OF FILE */
572