]>
Commit | Line | Data |
---|---|---|
c7de829c WD |
1 | /**************************************************************************** |
2 | * | |
3 | * SciTech OS Portability Manager Library | |
4 | * | |
5 | * ======================================================================== | |
6 | * | |
7 | * The contents of this file are subject to the SciTech MGL Public | |
8 | * License Version 1.0 (the "License"); you may not use this file | |
9 | * except in compliance with the License. You may obtain a copy of | |
10 | * the License at http://www.scitechsoft.com/mgl-license.txt | |
11 | * | |
12 | * Software distributed under the License is distributed on an | |
13 | * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | |
14 | * implied. See the License for the specific language governing | |
15 | * rights and limitations under the License. | |
16 | * | |
17 | * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. | |
18 | * | |
19 | * The Initial Developer of the Original Code is SciTech Software, Inc. | |
20 | * All Rights Reserved. | |
21 | * | |
22 | * ======================================================================== | |
23 | * | |
24 | * Portions copyright (C) Josh Vanderhoof | |
25 | * | |
26 | * Language: ANSI C | |
27 | * Environment: Any | |
28 | * | |
29 | * Description: Functions to save and restore the VGA hardware state. | |
30 | * | |
31 | ****************************************************************************/ | |
32 | ||
33 | #include "pmapi.h" | |
34 | #if defined(__WIN32_VXD__) || defined(__NT_DRIVER__) | |
35 | #include "sdd/sddhelp.h" | |
36 | #else | |
37 | #include <string.h> | |
38 | #endif | |
39 | ||
40 | /*--------------------------- Global variables ----------------------------*/ | |
41 | ||
42 | /* VGA index register ports */ | |
43 | #define CRT_I 0x3D4 /* CRT Controller Index */ | |
44 | #define ATT_IW 0x3C0 /* Attribute Controller Index & Data */ | |
45 | #define GRA_I 0x3CE /* Graphics Controller Index */ | |
46 | #define SEQ_I 0x3C4 /* Sequencer Index */ | |
47 | ||
48 | /* VGA data register ports */ | |
49 | #define CRT_D 0x3D5 /* CRT Controller Data Register */ | |
50 | #define ATT_R 0x3C1 /* Attribute Controller Data Read Register */ | |
51 | #define GRA_D 0x3CF /* Graphics Controller Data Register */ | |
52 | #define SEQ_D 0x3C5 /* Sequencer Data Register */ | |
53 | #define MIS_R 0x3CC /* Misc Output Read Register */ | |
54 | #define MIS_W 0x3C2 /* Misc Output Write Register */ | |
55 | #define IS1_R 0x3DA /* Input Status Register 1 */ | |
56 | #define PEL_IW 0x3C8 /* PEL Write Index */ | |
57 | #define PEL_IR 0x3C7 /* PEL Read Index */ | |
58 | #define PEL_D 0x3C9 /* PEL Data Register */ | |
59 | ||
60 | /* standard VGA indexes max counts */ | |
61 | #define CRT_C 24 /* 24 CRT Controller Registers */ | |
62 | #define ATT_C 21 /* 21 Attribute Controller Registers */ | |
63 | #define GRA_C 9 /* 9 Graphics Controller Registers */ | |
64 | #define SEQ_C 5 /* 5 Sequencer Registers */ | |
65 | #define MIS_C 1 /* 1 Misc Output Register */ | |
66 | #define PAL_C 768 /* 768 Palette Registers */ | |
67 | #define FONT_C 8192 /* Total size of character generator RAM */ | |
68 | ||
69 | /* VGA registers saving indexes */ | |
70 | #define CRT 0 /* CRT Controller Registers start */ | |
71 | #define ATT (CRT+CRT_C) /* Attribute Controller Registers start */ | |
72 | #define GRA (ATT+ATT_C) /* Graphics Controller Registers start */ | |
73 | #define SEQ (GRA+GRA_C) /* Sequencer Registers */ | |
74 | #define MIS (SEQ+SEQ_C) /* General Registers */ | |
75 | #define PAL (MIS+MIS_C) /* VGA Palette Registers */ | |
76 | #define FONT (PAL+PAL_C) /* VGA font data */ | |
77 | ||
78 | /* Macros for port I/O with arguments reversed */ | |
79 | ||
80 | #define _port_out(v,p) PM_outpb(p,(uchar)(v)) | |
81 | #define _port_in(p) PM_inpb(p) | |
82 | ||
83 | /*----------------------------- Implementation ----------------------------*/ | |
84 | ||
85 | /**************************************************************************** | |
86 | REMARKS: | |
87 | Returns the size of the VGA state buffer. | |
88 | ****************************************************************************/ | |
89 | int PMAPI PM_getVGAStateSize(void) | |
90 | { | |
91 | return CRT_C + ATT_C + GRA_C + SEQ_C + MIS_C + PAL_C + FONT_C; | |
92 | } | |
93 | ||
94 | /**************************************************************************** | |
95 | REMARKS: | |
96 | Delay for a short period of time. | |
97 | ****************************************************************************/ | |
98 | static void vga_delay(void) | |
99 | { | |
100 | int i; | |
101 | ||
102 | /* For the loop here we program the POST register. The length of this | |
103 | * delay is dependant only on ISA bus speed, but it is enough for | |
104 | * what we need. | |
105 | */ | |
106 | for (i = 0; i <= 10; i++) | |
8bde7f77 | 107 | PM_outpb(0x80, 0); |
c7de829c WD |
108 | } |
109 | ||
110 | /**************************************************************************** | |
111 | PARAMETERS: | |
112 | port - I/O port to read value from | |
113 | index - Port index to read | |
114 | ||
115 | RETURNS: | |
116 | Byte read from 'port' register 'index'. | |
117 | ****************************************************************************/ | |
118 | static ushort vga_rdinx( | |
119 | ushort port, | |
120 | ushort index) | |
121 | { | |
122 | PM_outpb(port,(uchar)index); | |
123 | return PM_inpb(port+1); | |
124 | } | |
125 | ||
126 | /**************************************************************************** | |
127 | PARAMETERS: | |
128 | port - I/O port to write to | |
129 | index - Port index to write | |
130 | value - Byte to write to port | |
131 | ||
132 | REMARKS: | |
133 | Writes a byte value to the 'port' register 'index'. | |
134 | ****************************************************************************/ | |
135 | static void vga_wrinx( | |
136 | ushort port, | |
137 | ushort index, | |
138 | ushort value) | |
139 | { | |
140 | PM_outpb(port,(uchar)index); | |
141 | PM_outpb(port+1,(uchar)value); | |
142 | } | |
143 | ||
144 | /**************************************************************************** | |
145 | REMARKS: | |
146 | Save the color palette values | |
147 | ****************************************************************************/ | |
148 | static void vga_savepalette( | |
149 | uchar *pal) | |
150 | { | |
151 | int i; | |
152 | ||
153 | _port_out(0, PEL_IR); | |
154 | for (i = 0; i < 768; i++) { | |
8bde7f77 WD |
155 | vga_delay(); |
156 | *pal++ = _port_in(PEL_D); | |
157 | } | |
c7de829c WD |
158 | } |
159 | ||
160 | /**************************************************************************** | |
161 | REMARKS: | |
162 | Restore the color palette values | |
163 | ****************************************************************************/ | |
164 | static void vga_restorepalette( | |
165 | const uchar *pal) | |
166 | { | |
167 | int i; | |
168 | ||
169 | /* restore saved palette */ | |
170 | _port_out(0, PEL_IW); | |
171 | for (i = 0; i < 768; i++) { | |
8bde7f77 WD |
172 | vga_delay(); |
173 | _port_out(*pal++, PEL_D); | |
174 | } | |
c7de829c WD |
175 | } |
176 | ||
177 | /**************************************************************************** | |
178 | REMARKS: | |
179 | Read the font data from the VGA character generator RAM | |
180 | ****************************************************************************/ | |
181 | static void vga_saveFont( | |
182 | uchar *data) | |
183 | { | |
184 | uchar *A0000Ptr = PM_getA0000Pointer(); | |
185 | uchar save[7]; | |
186 | ||
187 | /* Enable access to character generator RAM */ | |
188 | save[0] = (uchar)vga_rdinx(SEQ_I,0x00); | |
189 | save[1] = (uchar)vga_rdinx(SEQ_I,0x02); | |
190 | save[2] = (uchar)vga_rdinx(SEQ_I,0x04); | |
191 | save[3] = (uchar)vga_rdinx(SEQ_I,0x00); | |
192 | save[4] = (uchar)vga_rdinx(GRA_I,0x04); | |
193 | save[5] = (uchar)vga_rdinx(GRA_I,0x05); | |
194 | save[6] = (uchar)vga_rdinx(GRA_I,0x06); | |
195 | vga_wrinx(SEQ_I,0x00,0x01); | |
196 | vga_wrinx(SEQ_I,0x02,0x04); | |
197 | vga_wrinx(SEQ_I,0x04,0x07); | |
198 | vga_wrinx(SEQ_I,0x00,0x03); | |
199 | vga_wrinx(GRA_I,0x04,0x02); | |
200 | vga_wrinx(GRA_I,0x05,0x00); | |
201 | vga_wrinx(GRA_I,0x06,0x00); | |
202 | ||
203 | /* Copy character generator RAM */ | |
204 | memcpy(data,A0000Ptr,FONT_C); | |
205 | ||
206 | /* Restore VGA state */ | |
207 | vga_wrinx(SEQ_I,0x00,save[0]); | |
208 | vga_wrinx(SEQ_I,0x02,save[1]); | |
209 | vga_wrinx(SEQ_I,0x04,save[2]); | |
210 | vga_wrinx(SEQ_I,0x00,save[3]); | |
211 | vga_wrinx(GRA_I,0x04,save[4]); | |
212 | vga_wrinx(GRA_I,0x05,save[5]); | |
213 | vga_wrinx(GRA_I,0x06,save[6]); | |
214 | } | |
215 | ||
216 | /**************************************************************************** | |
217 | REMARKS: | |
218 | Downloads the font data to the VGA character generator RAM | |
219 | ****************************************************************************/ | |
220 | static void vga_restoreFont( | |
221 | const uchar *data) | |
222 | { | |
223 | uchar *A0000Ptr = PM_getA0000Pointer(); | |
224 | ||
225 | /* Enable access to character generator RAM */ | |
226 | vga_wrinx(SEQ_I,0x00,0x01); | |
227 | vga_wrinx(SEQ_I,0x02,0x04); | |
228 | vga_wrinx(SEQ_I,0x04,0x07); | |
229 | vga_wrinx(SEQ_I,0x00,0x03); | |
230 | vga_wrinx(GRA_I,0x04,0x02); | |
231 | vga_wrinx(GRA_I,0x05,0x00); | |
232 | vga_wrinx(GRA_I,0x06,0x00); | |
233 | ||
234 | /* Copy font back to character generator RAM */ | |
235 | memcpy(A0000Ptr,data,FONT_C); | |
236 | } | |
237 | ||
238 | /**************************************************************************** | |
239 | REMARKS: | |
240 | Save the state of all VGA compatible registers | |
241 | ****************************************************************************/ | |
242 | void PMAPI PM_saveVGAState( | |
243 | void *stateBuf) | |
244 | { | |
245 | uchar *regs = stateBuf; | |
246 | int i; | |
247 | ||
248 | /* Save state of VGA registers */ | |
249 | for (i = 0; i < CRT_C; i++) { | |
8bde7f77 WD |
250 | _port_out(i, CRT_I); |
251 | regs[CRT + i] = _port_in(CRT_D); | |
252 | } | |
c7de829c | 253 | for (i = 0; i < ATT_C; i++) { |
8bde7f77 WD |
254 | _port_in(IS1_R); |
255 | vga_delay(); | |
256 | _port_out(i, ATT_IW); | |
257 | vga_delay(); | |
258 | regs[ATT + i] = _port_in(ATT_R); | |
259 | vga_delay(); | |
260 | } | |
c7de829c | 261 | for (i = 0; i < GRA_C; i++) { |
8bde7f77 WD |
262 | _port_out(i, GRA_I); |
263 | regs[GRA + i] = _port_in(GRA_D); | |
264 | } | |
c7de829c | 265 | for (i = 0; i < SEQ_C; i++) { |
8bde7f77 WD |
266 | _port_out(i, SEQ_I); |
267 | regs[SEQ + i] = _port_in(SEQ_D); | |
268 | } | |
c7de829c WD |
269 | regs[MIS] = _port_in(MIS_R); |
270 | ||
271 | /* Save the VGA palette values */ | |
272 | vga_savepalette(®s[PAL]); | |
273 | ||
274 | /* Save the VGA character generator RAM */ | |
275 | vga_saveFont(®s[FONT]); | |
276 | ||
277 | /* Turn the VGA display back on */ | |
278 | PM_vgaUnblankDisplay(); | |
279 | } | |
280 | ||
281 | /**************************************************************************** | |
282 | REMARKS: | |
283 | Retore the state of all VGA compatible registers | |
284 | ****************************************************************************/ | |
285 | void PMAPI PM_restoreVGAState( | |
286 | const void *stateBuf) | |
287 | { | |
288 | const uchar *regs = stateBuf; | |
289 | int i; | |
290 | ||
291 | /* Blank the display before we start the restore */ | |
292 | PM_vgaBlankDisplay(); | |
293 | ||
294 | /* Restore the VGA character generator RAM */ | |
295 | vga_restoreFont(®s[FONT]); | |
296 | ||
297 | /* Restore the VGA palette values */ | |
298 | vga_restorepalette(®s[PAL]); | |
299 | ||
300 | /* Restore the state of the VGA compatible registers */ | |
301 | _port_out(regs[MIS], MIS_W); | |
302 | ||
303 | /* Delay to allow clock change to settle */ | |
304 | for (i = 0; i < 10; i++) | |
8bde7f77 | 305 | vga_delay(); |
c7de829c WD |
306 | |
307 | /* Synchronous reset on */ | |
308 | _port_out(0x00,SEQ_I); | |
309 | _port_out(0x01,SEQ_D); | |
310 | ||
311 | /* Write seqeuencer registers */ | |
312 | _port_out(1, SEQ_I); | |
313 | _port_out(regs[SEQ + 1] | 0x20, SEQ_D); | |
314 | for (i = 2; i < SEQ_C; i++) { | |
8bde7f77 WD |
315 | _port_out(i, SEQ_I); |
316 | _port_out(regs[SEQ + i], SEQ_D); | |
317 | } | |
c7de829c WD |
318 | |
319 | /* Synchronous reset off */ | |
320 | _port_out(0x00,SEQ_I); | |
321 | _port_out(0x03,SEQ_D); | |
322 | ||
323 | /* Deprotect CRT registers 0-7 and write CRTC */ | |
324 | _port_out(0x11, CRT_I); | |
325 | _port_out(_port_in(CRT_D) & 0x7F, CRT_D); | |
326 | for (i = 0; i < CRT_C; i++) { | |
8bde7f77 WD |
327 | _port_out(i, CRT_I); |
328 | _port_out(regs[CRT + i], CRT_D); | |
329 | } | |
c7de829c | 330 | for (i = 0; i < GRA_C; i++) { |
8bde7f77 WD |
331 | _port_out(i, GRA_I); |
332 | _port_out(regs[GRA + i], GRA_D); | |
333 | } | |
c7de829c | 334 | for (i = 0; i < ATT_C; i++) { |
8bde7f77 WD |
335 | _port_in(IS1_R); /* reset flip-flop */ |
336 | vga_delay(); | |
337 | _port_out(i, ATT_IW); | |
338 | vga_delay(); | |
339 | _port_out(regs[ATT + i], ATT_IW); | |
340 | vga_delay(); | |
341 | } | |
c7de829c WD |
342 | |
343 | /* Ensure the VGA screen is turned on */ | |
344 | PM_vgaUnblankDisplay(); | |
345 | } | |
346 | ||
347 | /**************************************************************************** | |
348 | REMARKS: | |
349 | Disables the VGA display for screen output making it blank. | |
350 | ****************************************************************************/ | |
351 | void PMAPI PM_vgaBlankDisplay(void) | |
352 | { | |
353 | /* Turn screen off */ | |
354 | _port_out(0x01, SEQ_I); | |
355 | _port_out(_port_in(SEQ_D) | 0x20, SEQ_D); | |
356 | ||
357 | /* Disable video output */ | |
358 | _port_in(IS1_R); | |
359 | vga_delay(); | |
360 | _port_out(0x00, ATT_IW); | |
361 | } | |
362 | ||
363 | /**************************************************************************** | |
364 | REMARKS: | |
365 | Enables the VGA display for screen output. | |
366 | ****************************************************************************/ | |
367 | void PMAPI PM_vgaUnblankDisplay(void) | |
368 | { | |
369 | /* Turn screen back on */ | |
370 | _port_out(0x01, SEQ_I); | |
371 | _port_out(_port_in(SEQ_D) & 0xDF, SEQ_D); | |
372 | ||
373 | /* Enable video output */ | |
374 | _port_in(IS1_R); | |
375 | vga_delay(); | |
376 | _port_out(0x20, ATT_IW); | |
377 | } |