2 Copyright (C) 1998 BJ Eirich (aka vecna)
\r
3 This program is free software; you can redistribute it and/or
\r
4 modify it under the terms of the GNU General Public License
\r
5 as published by the Free Software Foundation; either version 2
\r
6 of the License, or (at your option) any later version.
\r
7 This program is distributed in the hope that it will be useful,
\r
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
\r
10 See the GNU General Public Lic
\r
11 See the GNU General Public License for more details.
\r
12 You should have received a copy of the GNU General Public License
\r
13 along with this program; if not, write to the Free Software
\r
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
18 #include <sys\nearptr.h>
\r
21 void BIOS_SetVideoMode(int mode)
\r
28 // =============================== Mode 13h ===================================
\r
30 int Mode13hShutdown(int i)
\r
32 if (i) BIOS_SetVideoMode(0x3);
\r
37 void InitMode13h(void)
\r
39 BIOS_SetVideoMode(0x13);
\r
41 DriverDesc = "320x200 (Mode 13h, linear)";
\r
47 // setup function drivers
\r
48 ShowPage=LFB_ShowPage;
\r
49 ShutdownVideo=Mode13hShutdown;
\r
51 video=(byte *) 0xA0000 + __djgpp_conventional_base;
\r
52 vscreen=(byte *) valloc(sx*sy, "vscreen", 0);
\r
54 memset(screen, 0, sx*sy);
\r
57 // ================================= Mode-X ==================================
\r
59 #define SEQU_ADDR 0x3c4
\r
60 #define CRTC_ADDR 0x3d4
\r
61 #define MISC_OUTPUT 0x3c2
\r
63 #define ATTRCON_ADDR 0x3c0
\r
64 #define MISC_ADDR 0x3c2
\r
65 #define VGAENABLE_ADDR 0x3c3
\r
66 #define SEQ_ADDR 0x3c4
\r
67 #define GRACON_ADDR 0x3ce
\r
68 #define CRTC_ADDR 0x3d4
\r
69 #define STATUS_ADDR 0x3da
\r
77 typedef Register *RegisterPtr;
\r
79 Register scr256x256[] =
\r
81 { 0x3c2, 0x00, 0xe3},{ 0x3d4, 0x00, 0x5f},{ 0x3d4, 0x01, 0x3f},
\r
82 { 0x3d4, 0x02, 0x40},{ 0x3d4, 0x03, 0x82},{ 0x3d4, 0x04, 0x4A},
\r
83 { 0x3d4, 0x05, 0x9A},{ 0x3d4, 0x06, 0x23},{ 0x3d4, 0x07, 0xb2},
\r
84 { 0x3d4, 0x08, 0x00},{ 0x3d4, 0x09, 0x61},{ 0x3d4, 0x10, 0x0a},
\r
85 { 0x3d4, 0x11, 0xac},{ 0x3d4, 0x12, 0xff},{ 0x3d4, 0x13, 0x20},
\r
86 { 0x3d4, 0x14, 0x40},{ 0x3d4, 0x15, 0x07},{ 0x3d4, 0x16, 0x1a},
\r
87 { 0x3d4, 0x17, 0xa3},{ 0x3c4, 0x01, 0x01},{ 0x3c4, 0x04, 0x0e},
\r
88 { 0x3ce, 0x05, 0x40},{ 0x3ce, 0x06, 0x05},{ 0x3c0, 0x10, 0x41},
\r
89 { 0x3c0, 0x13, 0x00}
\r
92 // ================================= Code ====================================
\r
97 outpw(0x03c4, (hi<<8)|0x02);
\r
100 int ModeXShutdown(int i)
\r
102 if (i) BIOS_SetVideoMode(0x3);
\r
107 int ModeXShowPage()
\r
113 if (key[SCAN_ALT] && key[SCAN_X]) err("Exiting: ALT-X pressed.");
\r
120 for (y=0; y<sy; ++y,d+=sx2)
\r
123 for (k=0; k<4; k++,s-=sx)
\r
126 for (x=0; x<sx2; x++,s+=4)
\r
134 static void outReg(Register r)
\r
138 // First handle special cases:
\r
141 // reset read/write flip-flop
\r
143 // ensure VGA output is enabled
\r
144 outp(ATTRCON_ADDR, r.index | 0x20);
\r
145 outp(ATTRCON_ADDR, r.value);
\r
149 case VGAENABLE_ADDR:
\r
150 // directly to the port
\r
151 outp(r.port, r.value);
\r
159 outp(r.port, r.index);
\r
161 outp(r.port + 1, r.value);
\r
166 // readyVgaRegs() does the initialization to make the VGA ready to
\r
167 // accept any combination of configuration register settings.
\r
169 // This involves enabling writes to index 0 to 7 of the CRT controller
\r
170 // (port 0x3d4), by clearing the most significant bit (bit 7) of index
\r
173 static void readyVgaRegs(void)
\r
178 v = inp(0x3d5) & 0x7f;
\r
183 // outRegArray sets n registers according to the array pointed to by r.
\r
184 // First, indexes 0-7 of the CRT controller are enabled for writing.
\r
186 static void outRegArray(Register *r, int n)
\r
195 DriverDesc = "256x256 (ModeX, planar)";
\r
197 outRegArray(scr256x256, sizeof(scr256x256) / sizeof (Register));
\r
202 cx2=sx-1, cy2=sy-1;
\r
208 DriverDesc = "320x240 (ModeX, planar)";
\r
210 outpw(SEQU_ADDR, 0x0604);
\r
211 memset((unsigned char *)0xA0000 + __djgpp_conventional_base,0,0x10000); // for clean mode switch
\r
212 outpw(SEQU_ADDR, 0x0110);
\r
213 outp(MISC_OUTPUT, 0xe3);
\r
214 outpw(SEQU_ADDR, 0x0300);
\r
215 outp(CRTC_ADDR, 0x11);
\r
216 in_byte = inp((CRTC_ADDR+1));
\r
217 in_byte = (in_byte && 0x7f);
\r
218 outp((CRTC_ADDR+1), in_byte);
\r
219 outpw(CRTC_ADDR, 0x0d06);
\r
220 outpw(CRTC_ADDR, 0x3e07);
\r
221 outpw(CRTC_ADDR, 0x4109);
\r
222 outpw(CRTC_ADDR, 0xea10);
\r
223 outpw(CRTC_ADDR, 0xac11);
\r
224 outpw(CRTC_ADDR, 0xdf12);
\r
225 outpw(CRTC_ADDR, 0x0014);
\r
226 outpw(CRTC_ADDR, 0xe715);
\r
227 outpw(CRTC_ADDR, 0x0616);
\r
228 outpw(CRTC_ADDR, 0xe317);
\r
233 cx2=sx-1, cy2=sy-1;
\r
239 DriverDesc = "360x240 (ModeX, planar)";
\r
241 outpw(SEQU_ADDR, 0x0604);
\r
242 memset((unsigned char *)0xA0000 + __djgpp_conventional_base,0,0x10000); // for clean mode switch
\r
243 outpw(SEQU_ADDR, 0x100);
\r
244 outp(MISC_OUTPUT, 0xe7);
\r
245 outpw(SEQU_ADDR, 0x300);
\r
246 outp(CRTC_ADDR, 0x11);
\r
247 in_byte = inp((CRTC_ADDR+1));
\r
248 in_byte = (in_byte && 0x7f);
\r
249 outp((CRTC_ADDR+1), in_byte);
\r
250 outpw(CRTC_ADDR, 0x6b00);
\r
251 outpw(CRTC_ADDR, 0x5901);
\r
252 outpw(CRTC_ADDR, 0x5a02);
\r
253 outpw(CRTC_ADDR, 0x8e03);
\r
254 outpw(CRTC_ADDR, 0x5e04);
\r
255 outpw(CRTC_ADDR, 0x8a05);
\r
256 outpw(CRTC_ADDR, 0x0d06);
\r
257 outpw(CRTC_ADDR, 0x3e07);
\r
258 outpw(CRTC_ADDR, 0x4109);
\r
259 outpw(CRTC_ADDR, 0xea10);
\r
260 outpw(CRTC_ADDR, 0xac11);
\r
261 outpw(CRTC_ADDR, 0xdf12);
\r
262 outpw(CRTC_ADDR, 0x2d13);
\r
263 outpw(CRTC_ADDR, 0x0014);
\r
264 outpw(CRTC_ADDR, 0xe715);
\r
265 outpw(CRTC_ADDR, 0x0616);
\r
266 outpw(CRTC_ADDR, 0xe317);
\r
271 cx2=sx-1, cy2=sy-1;
\r
274 void InitModeX(int xres, int yres)
\r
278 BIOS_SetVideoMode(0x13);
\r
281 if (xres==320 && yres==240) { Set320x240(); found=1; }
\r
282 if (xres==360 && yres==240) { Set360x240(); found=1; }
\r
283 if (xres==256 && yres==256) { Set256x256(); found=1; }
\r
287 // resolution not found, bitch...
\r
288 err("Internal error: unknown ModeX resolution");
\r
290 // resolution found..
\r
293 ShowPage=LFB_ShowPage;
\r
294 if (xres != 256 && yres != 256)
\r
295 ShowPage=ModeXShowPage;
\r
296 ShutdownVideo=ModeXShutdown;
\r
299 video=(byte *) 0xA0000 + __djgpp_conventional_base;
\r
300 vscreen=(byte *) valloc(sx*sy, "vscreen", 0);
\r
302 memset(screen, 0, sx*sy);
\r
305 // ================================= VESA ====================================
\r
307 int VESAShutdown(int i)
\r
309 if (i) BIOS_SetVideoMode(0x3);
\r
314 void VESASetBank(int bank)
\r
320 INTERRUPT(0x10, r);
\r
323 int VESAShowPage(void)
\r
329 if (key[SCAN_ALT] && key[SCAN_X]) err("Exiting: ALT-X pressed.");
\r
338 VESASetBank(bank++);
\r
340 // *** no padding exists now, can be rewritten smaller/faster - aen
\r
350 { memcpy(d,s,bytes);
\r
354 VESASetBank(bank++);
\r
372 DriverDesc = "640x480 (VESA, Banked)";
\r
376 INTERRUPT(0x10, r);
\r
384 void InitVESA(int xres, int yres)
\r
389 if (xres==640 && yres==480) { Set640x480(); found=1; }
\r
392 err("Internal error: unknown VESA resolution");
\r
394 // setup driver functions
\r
395 ShowPage = VESAShowPage; // reassign for banked VESA video blt
\r
396 ShutdownVideo = VESAShutdown;
\r
398 video=(byte *) 0xA0000 + __djgpp_conventional_base;
\r
399 vscreen=(byte *) valloc(sx*sy, "vscreen", 0);
\r
401 memset(screen, 0, sx*sy);
\r
404 // ============================================================================
\r
406 int InitVideo(int xres, int yres)
\r
411 if (xres==320 && yres==200) { InitMode13h(); found=1; }
\r
412 if (xres==320 && yres==240) { InitModeX(xres,yres); found=1; }
\r
413 if (xres==360 && yres==240) { InitModeX(xres,yres); found=1; }
\r
414 if (xres==256 && yres==256) { InitModeX(xres,yres); found=1; }
\r
415 if (xres==640 && yres==480) { InitVESA(xres,yres); found=1; }
\r
419 tsx=xres; tsy=yres;
\r
420 Logp("Sys: Initializing %s.", DriverDesc);
\r
421 InitMouse(tsx, tsy);
\r
427 Logp("Unknown video mode %dx%d; defaulting to mode 13h.", xres, yres);
\r
428 InitMouse(tsx, tsy);
\r