Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpcvideo.c
Go to the documentation of this file.
00001 /* $Id: pcvideo.c 56137 2012-03-12 23:00:56Z pschweitzer $ 00002 * 00003 * FreeLoader 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License along 00016 * with this program; if not, write to the Free Software Foundation, Inc., 00017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00018 */ 00019 00020 #include <freeldr.h> 00021 00022 #define NDEBUG 00023 #include <debug.h> 00024 00025 #define VIDEOPORT_PALETTE_READ 0x03C7 00026 #define VIDEOPORT_PALETTE_WRITE 0x03C8 00027 #define VIDEOPORT_PALETTE_DATA 0x03C9 00028 #define VIDEOPORT_VERTICAL_RETRACE 0x03DA 00029 00030 #define VIDEOVGA_MEM_ADDRESS 0xA0000 00031 #define VIDEOTEXT_MEM_ADDRESS 0xB8000 00032 #define VIDEOTEXT_MEM_SIZE 0x8000 00033 00034 #define VIDEOCARD_CGA_OR_OTHER 0 00035 #define VIDEOCARD_EGA 1 00036 #define VIDEOCARD_VGA 2 00037 00038 #define VIDEOMODE_NORMAL_TEXT 0 00039 #define VIDEOMODE_EXTENDED_TEXT 1 00040 #define VIDEOMODE_80X28 0x501C 00041 #define VIDEOMODE_80X30 0x501E 00042 #define VIDEOMODE_80X34 0x5022 00043 #define VIDEOMODE_80X43 0x502B 00044 #define VIDEOMODE_80X60 0x503C 00045 #define VIDEOMODE_132X25 0x8419 00046 #define VIDEOMODE_132X43 0x842B 00047 #define VIDEOMODE_132X50 0x8432 00048 #define VIDEOMODE_132X60 0x843C 00049 00050 #define VERTRES_200_SCANLINES 0x00 00051 #define VERTRES_350_SCANLINES 0x01 00052 #define VERTRES_400_SCANLINES 0x02 00053 00054 DBG_DEFAULT_CHANNEL(UI); 00055 00056 #include <pshpack2.h> 00057 typedef struct 00058 { 00059 USHORT ModeAttributes; /* mode attributes (see #00080) */ 00060 UCHAR WindowAttributesA; /* window attributes, window A (see #00081) */ 00061 UCHAR WindowsAttributesB; /* window attributes, window B (see #00081) */ 00062 USHORT WindowGranularity; /* window granularity in KB */ 00063 USHORT WindowSize; /* window size in KB */ 00064 USHORT WindowAStartSegment; /* start segment of window A (0000h if not supported) */ 00065 USHORT WindowBStartSegment; /* start segment of window B (0000h if not supported) */ 00066 ULONG WindowPositioningFunction; /* -> FAR window positioning function (equivalent to AX=4F05h) */ 00067 USHORT BytesPerScanLine; /* bytes per scan line */ 00068 /* ---remainder is optional for VESA modes in v1.0/1.1, needed for OEM modes--- */ 00069 USHORT WidthInPixels; /* width in pixels (graphics) or characters (text) */ 00070 USHORT HeightInPixels; /* height in pixels (graphics) or characters (text) */ 00071 UCHAR CharacterWidthInPixels; /* width of character cell in pixels */ 00072 UCHAR CharacterHeightInPixels; /* height of character cell in pixels */ 00073 UCHAR NumberOfMemoryPlanes; /* number of memory planes */ 00074 UCHAR BitsPerPixel; /* number of bits per pixel */ 00075 UCHAR NumberOfBanks; /* number of banks */ 00076 UCHAR MemoryModel; /* memory model type (see #00082) */ 00077 UCHAR BankSize; /* size of bank in KB */ 00078 UCHAR NumberOfImagePanes; /* number of image pages (less one) that will fit in video RAM */ 00079 UCHAR Reserved1; /* reserved (00h for VBE 1.0-2.0, 01h for VBE 3.0) */ 00080 /* ---VBE v1.2+ --- */ 00081 UCHAR RedMaskSize; /* red mask size */ 00082 UCHAR RedMaskPosition; /* red field position */ 00083 UCHAR GreenMaskSize; /* green mask size */ 00084 UCHAR GreenMaskPosition; /* green field size */ 00085 UCHAR BlueMaskSize; /* blue mask size */ 00086 UCHAR BlueMaskPosition; /* blue field size */ 00087 UCHAR ReservedMaskSize; /* reserved mask size */ 00088 UCHAR ReservedMaskPosition; /* reserved mask position */ 00089 UCHAR DirectColorModeInfo; /* direct color mode info */ 00090 /* bit 0:Color ramp is programmable */ 00091 /* bit 1:Bytes in reserved field may be used by application */ 00092 /* ---VBE v2.0+ --- */ 00093 ULONG LinearVideoBufferAddress; /* physical address of linear video buffer */ 00094 ULONG OffscreenMemoryPointer; /* pointer to start of offscreen memory */ 00095 USHORT OffscreenMemorySize; /* KB of offscreen memory */ 00096 /* ---VBE v3.0 --- */ 00097 USHORT LinearBytesPerScanLine; /* bytes per scan line in linear modes */ 00098 UCHAR BankedNumberOfImages; /* number of images (less one) for banked video modes */ 00099 UCHAR LinearNumberOfImages; /* number of images (less one) for linear video modes */ 00100 UCHAR LinearRedMaskSize; /* linear modes:Size of direct color red mask (in bits) */ 00101 UCHAR LinearRedMaskPosition; /* linear modes:Bit position of red mask LSB (e.g. shift count) */ 00102 UCHAR LinearGreenMaskSize; /* linear modes:Size of direct color green mask (in bits) */ 00103 UCHAR LinearGreenMaskPosition; /* linear modes:Bit position of green mask LSB (e.g. shift count) */ 00104 UCHAR LinearBlueMaskSize; /* linear modes:Size of direct color blue mask (in bits) */ 00105 UCHAR LinearBlueMaskPosition; /* linear modes:Bit position of blue mask LSB (e.g. shift count) */ 00106 UCHAR LinearReservedMaskSize; /* linear modes:Size of direct color reserved mask (in bits) */ 00107 UCHAR LinearReservedMaskPosition; /* linear modes:Bit position of reserved mask LSB */ 00108 ULONG MaximumPixelClock; /* maximum pixel clock for graphics video mode, in Hz */ 00109 UCHAR Reserved2[190]; /* 190 BYTEs reserved (0) */ 00110 } SVGA_MODE_INFORMATION, *PSVGA_MODE_INFORMATION; 00111 #include <poppack.h> 00112 00113 static USHORT BiosVideoMode; /* Current video mode as known by BIOS */ 00114 static ULONG ScreenWidth = 80; /* Screen Width in characters */ 00115 static ULONG ScreenHeight = 25; /* Screen Height in characters */ 00116 static ULONG BytesPerScanLine = 160; /* Number of bytes per scanline (delta) */ 00117 static VIDEODISPLAYMODE DisplayMode = VideoTextMode; /* Current display mode */ 00118 static BOOLEAN VesaVideoMode = FALSE; /* Are we using a VESA mode? */ 00119 static SVGA_MODE_INFORMATION VesaVideoModeInformation; /* Only valid when in VESA mode */ 00120 static ULONG CurrentMemoryBank = 0; /* Currently selected VESA bank */ 00121 00122 static ULONG 00123 PcVideoDetectVideoCard(VOID) 00124 { 00125 REGS Regs; 00126 00127 /* Int 10h AH=12h BL=10h 00128 * VIDEO - ALTERNATE FUNCTION SELECT (PS,EGA,VGA,MCGA) - GET EGA INFO 00129 * 00130 * AH = 12h 00131 * BL = 10h 00132 * Return: 00133 * BH = video state 00134 * 00h color mode in effect (I/O port 3Dxh) 00135 * 01h mono mode in effect (I/O port 3Bxh) 00136 * BL = installed memory (00h = 64K, 01h = 128K, 02h = 192K, 03h = 256K) 00137 * CH = feature connector bits 00138 * CL = switch settings 00139 * AH destroyed (at least by Tseng ET4000 BIOS v8.00n) 00140 * 00141 * Installation check;EGA 00142 */ 00143 Regs.b.ah = 0x12; 00144 Regs.b.bl = 0x10; 00145 Int386(0x10, &Regs, &Regs); 00146 00147 /* If BL is still equal to 0x10 then there is no EGA/VGA present */ 00148 if (0x10 == Regs.b.bl) 00149 { 00150 return VIDEOCARD_CGA_OR_OTHER; 00151 } 00152 00153 /* Int 10h AX=1A00h 00154 * VIDEO - GET DISPLAY COMBINATION CODE (PS,VGA/MCGA) 00155 * 00156 * AX = 1A00h 00157 * Return: 00158 * AL = 1Ah if function was supported 00159 * BL = active display code 00160 * BH = alternate display code 00161 * 00162 * This function is commonly used to check for the presence of a VGA. 00163 * 00164 * Installation check;VGA 00165 * 00166 * Values for display combination code: 00167 * 00h no display 00168 * 01h monochrome adapter w/ monochrome display 00169 * 02h CGA w/ color display 00170 * 03h reserved 00171 * 04h EGA w/ color display 00172 * 05h EGA w/ monochrome display 00173 * 06h PGA w/ color display 00174 * 07h VGA w/ monochrome analog display 00175 * 08h VGA w/ color analog display 00176 * 09h reserved 00177 * 0Ah MCGA w/ digital color display 00178 * 0Bh MCGA w/ monochrome analog display 00179 * 0Ch MCGA w/ color analog display 00180 * FFh unknown display type 00181 */ 00182 Regs.b.ah = 0x12; 00183 Regs.b.bl = 0x10; 00184 Int386(0x10, &Regs, &Regs); 00185 00186 if (0x1a == Regs.b.al) 00187 { 00188 return VIDEOCARD_VGA; 00189 } 00190 else 00191 { 00192 return VIDEOCARD_EGA; 00193 } 00194 } 00195 00196 static VOID PcVideoSetBiosMode(UCHAR VideoMode) 00197 { 00198 REGS Regs; 00199 00200 /* Int 10h AH=00h 00201 * VIDEO - SET VIDEO MODE 00202 * 00203 * AH = 00h 00204 * AL = desired video mode 00205 * Return: 00206 * AL = video mode flag (Phoenix, AMI BIOS) 00207 * 20h mode > 7 00208 * 30h modes 0-5 and 7 00209 * 3Fh mode 6 00210 * AL = CRT controller mode byte (Phoenix 386 BIOS v1.10) 00211 */ 00212 Regs.b.ah = 0x00; 00213 Regs.b.al = VideoMode; 00214 Int386(0x10, &Regs, &Regs); 00215 } 00216 00217 static VOID 00218 PcVideoSetFont8x8(VOID) 00219 { 00220 REGS Regs; 00221 00222 /* Int 10h AX=1112h 00223 * VIDEO - TEXT-MODE CHARGEN - LOAD ROM 8x8 DBL-DOT PATTERNS (PS,EGA,VGA) 00224 * 00225 * AX = 1112h 00226 * BL = block to load 00227 * Return: 00228 * Nothing 00229 */ 00230 Regs.w.ax = 0x1112; 00231 Regs.b.bl = 0x00; 00232 Int386(0x10, &Regs, &Regs); 00233 } 00234 00235 static VOID 00236 PcVideoSetFont8x14(VOID) 00237 { 00238 REGS Regs; 00239 00240 /* Int 10h AX=1111h 00241 * VIDEO - TEXT-MODE CHARGEN - LOAD ROM MONOCHROME PATTERNS (PS,EGA,VGA) 00242 * 00243 * AX = 1111h 00244 * BL = block to load 00245 * Return: 00246 * Nothing 00247 */ 00248 Regs.w.ax = 0x1111; 00249 Regs.b.bl = 0; 00250 Int386(0x10, &Regs, &Regs); 00251 } 00252 00253 static VOID 00254 PcVideoSelectAlternatePrintScreen(VOID) 00255 { 00256 REGS Regs; 00257 00258 /* Int 10h AH=12h BL=20h 00259 * VIDEO - ALTERNATE FUNCTION SELECT (PS,EGA,VGA,MCGA) - ALTERNATE PRTSC 00260 * 00261 * AH = 12h 00262 * BL = 20h select alternate print screen routine 00263 * Return: 00264 * Nothing 00265 * 00266 * Installs a PrtSc routine from the video card's BIOS to replace the 00267 * default PrtSc handler from the ROM BIOS, which usually does not 00268 * understand screen heights other than 25 lines. 00269 * 00270 * Some adapters disable print-screen instead of enhancing it. 00271 */ 00272 Regs.b.ah = 0x12; 00273 Regs.b.bl = 0x20; 00274 Int386(0x10, &Regs, &Regs); 00275 } 00276 00277 static VOID 00278 PcVideoDisableCursorEmulation(VOID) 00279 { 00280 REGS Regs; 00281 00282 /* Int 10h AH=12h BL=34h 00283 * VIDEO - ALTERNATE FUNCTION SELECT (VGA) - CURSOR EMULATION 00284 * 00285 * AH = 12h 00286 * BL = 34h 00287 * AL = new state 00288 * 00h enable alphanumeric cursor emulation 00289 * 01h disable alphanumeric cursor emulation 00290 * Return: 00291 * AL = 12h if function supported 00292 * 00293 * Specify whether the BIOS should automatically remap cursor start/end 00294 * according to the current character height in text modes. 00295 */ 00296 Regs.b.ah = 0x12; 00297 Regs.b.bl = 0x34; 00298 Regs.b.al = 0x01; 00299 Int386(0x10, &Regs, &Regs); 00300 } 00301 00302 static VOID 00303 PcVideoDefineCursor(UCHAR StartScanLine, UCHAR EndScanLine) 00304 { 00305 REGS Regs; 00306 00307 /* Int 10h AH=01h 00308 * VIDEO - SET TEXT-MODE CURSOR SHAPE 00309 * 00310 * AH = 01h 00311 * CH = cursor start and options 00312 * CL = bottom scan line containing cursor (bits 0-4) 00313 * Return: 00314 * Nothing 00315 * 00316 * Specify the starting and ending scan lines to be occupied 00317 * by the hardware cursor in text modes. 00318 * 00319 * AMI 386 BIOS and AST Premier 386 BIOS will lock up the 00320 * system if AL is not equal to the current video mode. 00321 * 00322 * Bitfields for cursor start and options: 00323 * 00324 * Bit(s) Description 00325 * 7 should be zero 00326 * 6,5 cursor blink 00327 * (00=normal, 01=invisible, 10=erratic, 11=slow). 00328 * (00=normal, other=invisible on EGA/VGA) 00329 * 4-0 topmost scan line containing cursor 00330 */ 00331 Regs.b.ah = 0x01; 00332 Regs.b.al = 0x03; 00333 Regs.b.ch = StartScanLine; 00334 Regs.b.cl = EndScanLine; 00335 Int386(0x10, &Regs, &Regs); 00336 } 00337 00338 static VOID 00339 PcVideoSetVerticalResolution(UCHAR VerticalResolutionMode) 00340 { 00341 REGS Regs; 00342 00343 /* Int 10h AH=12h BL=30h 00344 * VIDEO - ALTERNATE FUNCTION SELECT (VGA) - SELECT VERTICAL RESOLUTION 00345 * 00346 * AH = 12h 00347 * BL = 30h 00348 * AL = vertical resolution 00349 * 00h 200 scan lines 00350 * 01h 350 scan lines 00351 * 02h 400 scan lines 00352 * Return: 00353 * AL = 12h if function supported 00354 * 00355 * Specifiy the number of scan lines used to display text modes. 00356 * 00357 * The specified resolution will take effect on the next mode set. 00358 */ 00359 Regs.b.ah = 0x12; 00360 Regs.b.bl = 0x30; 00361 Regs.b.al = VerticalResolutionMode; 00362 Int386(0x10, &Regs, &Regs); 00363 } 00364 00365 static VOID 00366 PcVideoSet480ScanLines(VOID) 00367 { 00368 INT_PTR CRTC; 00369 00370 /* Read CRTC port */ 00371 CRTC = READ_PORT_UCHAR((PUCHAR)0x03CC); 00372 00373 if (CRTC & 1) 00374 { 00375 CRTC = 0x3D4; 00376 } 00377 else 00378 { 00379 CRTC = 0x3B4; 00380 } 00381 00382 /* Vertical sync end (also unlocks CR0-7) */ 00383 WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x11); 00384 WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0x0C); 00385 00386 /* Vertical total */ 00387 WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x06); 00388 WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0x0B); 00389 00390 /* (vertical) overflow */ 00391 WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x07); 00392 WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0x3E); 00393 00394 /* Vertical sync start */ 00395 WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x10); 00396 WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0xEA); 00397 00398 /* Vertical display end */ 00399 WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x12); 00400 WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0xDF); 00401 00402 /* Vertical blank start */ 00403 WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x15); 00404 WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0xE7); 00405 00406 /* Vertical blank end */ 00407 WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x16); 00408 WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0x04); 00409 00410 /* Misc output register (read) */ 00411 CRTC = READ_PORT_UCHAR((PUCHAR)0x03CC); 00412 00413 /* Preserve clock select bits and color bit */ 00414 CRTC = (CRTC & 0x0D); 00415 /* Set correct sync polarity */ 00416 CRTC = (CRTC | 0xE2); 00417 00418 /* (write) */ 00419 WRITE_PORT_UCHAR((PUCHAR)0x03C2, (UCHAR)CRTC); 00420 } 00421 00422 static VOID 00423 PcVideoSetDisplayEnd(VOID) 00424 { 00425 INT_PTR CRTC; 00426 00427 /* Read CRTC port */ 00428 CRTC = READ_PORT_UCHAR((PUCHAR)0x03CC); 00429 00430 if (CRTC & 1) 00431 { 00432 CRTC = 0x3D4; 00433 } 00434 else 00435 { 00436 CRTC = 0x3B4; 00437 } 00438 00439 /* Vertical display end */ 00440 WRITE_PORT_UCHAR((PUCHAR)CRTC, 0x12); 00441 WRITE_PORT_UCHAR((PUCHAR)CRTC+1, 0xDF); 00442 } 00443 00444 static BOOLEAN 00445 PcVideoVesaGetSVGAModeInformation(USHORT Mode, PSVGA_MODE_INFORMATION ModeInformation) 00446 { 00447 REGS Regs; 00448 00449 RtlZeroMemory((PVOID)BIOSCALLBUFFER, 256); 00450 00451 /* VESA SuperVGA BIOS - GET SuperVGA MODE INFORMATION 00452 * AX = 4F01h 00453 * CX = SuperVGA video mode (see #04082 for bitfields) 00454 * ES:DI -> 256-byte buffer for mode information (see #00079) 00455 * Return: 00456 * AL = 4Fh if function supported 00457 * AH = status 00458 * 00h successful 00459 * ES:DI buffer filled 00460 * 01h failed 00461 * 00462 * Desc: Determine the attributes of the specified video mode 00463 * 00464 * Note: While VBE 1.1 and higher will zero out all unused bytes 00465 * of the buffer, v1.0 did not, so applications that want to be 00466 * backward compatible should clear the buffer before calling 00467 */ 00468 Regs.w.ax = 0x4F01; 00469 Regs.w.cx = Mode; 00470 Regs.w.es = BIOSCALLBUFSEGMENT; 00471 Regs.w.di = BIOSCALLBUFOFFSET; 00472 Int386(0x10, &Regs, &Regs); 00473 00474 if (Regs.w.ax != 0x004F) 00475 { 00476 return FALSE; 00477 } 00478 00479 RtlCopyMemory(ModeInformation, (PVOID)BIOSCALLBUFFER, sizeof(SVGA_MODE_INFORMATION)); 00480 00481 TRACE("\n"); 00482 TRACE("BiosVesaGetSVGAModeInformation() mode 0x%x\n", Mode); 00483 TRACE("ModeAttributes = 0x%x\n", ModeInformation->ModeAttributes); 00484 TRACE("WindowAttributesA = 0x%x\n", ModeInformation->WindowAttributesA); 00485 TRACE("WindowAttributesB = 0x%x\n", ModeInformation->WindowsAttributesB); 00486 TRACE("WindowGranularity = %dKB\n", ModeInformation->WindowGranularity); 00487 TRACE("WindowSize = %dKB\n", ModeInformation->WindowSize); 00488 TRACE("WindowAStartSegment = 0x%x\n", ModeInformation->WindowAStartSegment); 00489 TRACE("WindowBStartSegment = 0x%x\n", ModeInformation->WindowBStartSegment); 00490 TRACE("WindowPositioningFunction = 0x%x\n", ModeInformation->WindowPositioningFunction); 00491 TRACE("BytesPerScanLine = %d\n", ModeInformation->BytesPerScanLine); 00492 TRACE("WidthInPixels = %d\n", ModeInformation->WidthInPixels); 00493 TRACE("HeightInPixels = %d\n", ModeInformation->HeightInPixels); 00494 TRACE("CharacterWidthInPixels = %d\n", ModeInformation->CharacterWidthInPixels); 00495 TRACE("CharacterHeightInPixels = %d\n", ModeInformation->CharacterHeightInPixels); 00496 TRACE("NumberOfMemoryPlanes = %d\n", ModeInformation->NumberOfMemoryPlanes); 00497 TRACE("BitsPerPixel = %d\n", ModeInformation->BitsPerPixel); 00498 TRACE("NumberOfBanks = %d\n", ModeInformation->NumberOfBanks); 00499 TRACE("MemoryModel = %d\n", ModeInformation->MemoryModel); 00500 TRACE("BankSize = %d\n", ModeInformation->BankSize); 00501 TRACE("NumberOfImagePlanes = %d\n", ModeInformation->NumberOfImagePanes); 00502 TRACE("---VBE v1.2+ ---\n"); 00503 TRACE("RedMaskSize = %d\n", ModeInformation->RedMaskSize); 00504 TRACE("RedMaskPosition = %d\n", ModeInformation->RedMaskPosition); 00505 TRACE("GreenMaskSize = %d\n", ModeInformation->GreenMaskSize); 00506 TRACE("GreenMaskPosition = %d\n", ModeInformation->GreenMaskPosition); 00507 TRACE("BlueMaskSize = %d\n", ModeInformation->BlueMaskSize); 00508 TRACE("BlueMaskPosition = %d\n", ModeInformation->BlueMaskPosition); 00509 TRACE("ReservedMaskSize = %d\n", ModeInformation->ReservedMaskSize); 00510 TRACE("ReservedMaskPosition = %d\n", ModeInformation->ReservedMaskPosition); 00511 TRACE("\n"); 00512 00513 return TRUE; 00514 } 00515 00516 static BOOLEAN 00517 PcVideoSetBiosVesaMode(USHORT Mode) 00518 { 00519 REGS Regs; 00520 00521 /* Int 10h AX=4F02h 00522 * VESA SuperVGA BIOS - SET SuperVGA VIDEO MODE 00523 * 00524 * AX = 4F02h 00525 * BX = new video mode 00526 * ES:DI -> (VBE 3.0+) CRTC information block, bit mode bit 11 set 00527 * Return: 00528 * AL = 4Fh if function supported 00529 * AH = status 00530 * 00h successful 00531 * 01h failed 00532 * 00533 * Values for VESA video mode: 00534 * 00h-FFh OEM video modes (see #00010 at AH=00h) 00535 * 100h 640x400x256 00536 * 101h 640x480x256 00537 * 102h 800x600x16 00538 * 103h 800x600x256 00539 * 104h 1024x768x16 00540 * 105h 1024x768x256 00541 * 106h 1280x1024x16 00542 * 107h 1280x1024x256 00543 * 108h 80x60 text 00544 * 109h 132x25 text 00545 * 10Ah 132x43 text 00546 * 10Bh 132x50 text 00547 * 10Ch 132x60 text 00548 * ---VBE v1.2+ --- 00549 * 10Dh 320x200x32K 00550 * 10Eh 320x200x64K 00551 * 10Fh 320x200x16M 00552 * 110h 640x480x32K 00553 * 111h 640x480x64K 00554 * 112h 640x480x16M 00555 * 113h 800x600x32K 00556 * 114h 800x600x64K 00557 * 115h 800x600x16M 00558 * 116h 1024x768x32K 00559 * 117h 1024x768x64K 00560 * 118h 1024x768x16M 00561 * 119h 1280x1024x32K (1:5:5:5) 00562 * 11Ah 1280x1024x64K (5:6:5) 00563 * 11Bh 1280x1024x16M 00564 * ---VBE 2.0+ --- 00565 * 120h 1600x1200x256 00566 * 121h 1600x1200x32K 00567 * 122h 1600x1200x64K 00568 * 81FFh special full-memory access mode 00569 * 00570 * Notes: The special mode 81FFh preserves the contents of the video memory and gives 00571 * access to all of the memory; VESA recommends that the special mode be a packed-pixel 00572 * mode. For VBE 2.0+, it is required that the VBE implement the mode, but not place it 00573 * in the list of available modes (mode information for this mode can be queried 00574 * directly, however).. As of VBE 2.0, VESA will no longer define video mode numbers 00575 */ 00576 Regs.w.ax = 0x4F02; 00577 Regs.w.bx = Mode; 00578 Int386(0x10, &Regs, &Regs); 00579 00580 if (0x004F != Regs.w.ax) 00581 { 00582 return FALSE; 00583 } 00584 00585 return TRUE; 00586 } 00587 00588 static BOOLEAN 00589 PcVideoSetMode80x25(VOID) 00590 { 00591 PcVideoSetBiosMode(0x03); 00592 ScreenWidth = 80; 00593 ScreenHeight = 25; 00594 00595 return TRUE; 00596 } 00597 00598 static BOOLEAN 00599 PcVideoSetMode80x50_80x43(VOID) 00600 { 00601 if (VIDEOCARD_VGA == PcVideoDetectVideoCard()) 00602 { 00603 PcVideoSetBiosMode(0x12); 00604 PcVideoSetFont8x8(); 00605 PcVideoSelectAlternatePrintScreen(); 00606 PcVideoDisableCursorEmulation(); 00607 PcVideoDefineCursor(6, 7); 00608 ScreenWidth = 80; 00609 ScreenHeight = 50; 00610 } 00611 else if (VIDEOCARD_EGA == PcVideoDetectVideoCard()) 00612 { 00613 PcVideoSetBiosMode(0x03); 00614 PcVideoSetFont8x8(); 00615 PcVideoSelectAlternatePrintScreen(); 00616 PcVideoDisableCursorEmulation(); 00617 PcVideoDefineCursor(6, 7); 00618 ScreenWidth = 80; 00619 ScreenHeight = 43; 00620 } 00621 else /* VIDEOCARD_CGA_OR_OTHER */ 00622 { 00623 return FALSE; 00624 } 00625 00626 return TRUE; 00627 } 00628 00629 static BOOLEAN 00630 PcVideoSetMode80x28(VOID) 00631 { 00632 /* FIXME: Is this VGA-only? */ 00633 PcVideoSetMode80x25(); 00634 PcVideoSetFont8x14(); 00635 PcVideoDefineCursor(11, 12); 00636 ScreenWidth = 80; 00637 ScreenHeight = 28; 00638 00639 return TRUE; 00640 } 00641 00642 static BOOLEAN 00643 PcVideoSetMode80x30(VOID) 00644 { 00645 /* FIXME: Is this VGA-only? */ 00646 PcVideoSetMode80x25(); 00647 PcVideoSet480ScanLines(); 00648 ScreenWidth = 80; 00649 ScreenHeight = 30; 00650 00651 return TRUE; 00652 } 00653 00654 static BOOLEAN 00655 PcVideoSetMode80x34(VOID) 00656 { 00657 /* FIXME: Is this VGA-only? */ 00658 PcVideoSetMode80x25(); 00659 PcVideoSet480ScanLines(); 00660 PcVideoSetFont8x14(); 00661 PcVideoDefineCursor(11, 12); 00662 PcVideoSetDisplayEnd(); 00663 ScreenWidth = 80; 00664 ScreenHeight = 34; 00665 00666 return TRUE; 00667 } 00668 00669 static BOOLEAN 00670 PcVideoSetMode80x43(VOID) 00671 { 00672 /* FIXME: Is this VGA-only? */ 00673 PcVideoSetVerticalResolution(VERTRES_350_SCANLINES); 00674 PcVideoSetMode80x25(); 00675 PcVideoSetFont8x8(); 00676 PcVideoSelectAlternatePrintScreen(); 00677 PcVideoDisableCursorEmulation(); 00678 PcVideoDefineCursor(6, 7); 00679 ScreenWidth = 80; 00680 ScreenHeight = 43; 00681 00682 return TRUE; 00683 } 00684 00685 static BOOLEAN 00686 PcVideoSetMode80x60(VOID) 00687 { 00688 /* FIXME: Is this VGA-only? */ 00689 PcVideoSetMode80x25(); 00690 PcVideoSet480ScanLines(); 00691 PcVideoSetFont8x8(); 00692 PcVideoSelectAlternatePrintScreen(); 00693 PcVideoDisableCursorEmulation(); 00694 PcVideoDefineCursor(6, 7); 00695 PcVideoSetDisplayEnd(); 00696 ScreenWidth = 80; 00697 ScreenHeight = 60; 00698 00699 return TRUE; 00700 } 00701 00702 static BOOLEAN 00703 PcVideoSetMode(USHORT NewMode) 00704 { 00705 CurrentMemoryBank = 0; 00706 00707 /* Set the values for the default text modes 00708 * If they are setting a graphics mode then 00709 * these values will be changed. 00710 */ 00711 BiosVideoMode = NewMode; 00712 ScreenWidth = 80; 00713 ScreenHeight = 25; 00714 BytesPerScanLine = 160; 00715 DisplayMode = VideoTextMode; 00716 VesaVideoMode = FALSE; 00717 00718 switch (NewMode) 00719 { 00720 case VIDEOMODE_NORMAL_TEXT: 00721 case 0x03: /* BIOS 80x25 text mode number */ 00722 return PcVideoSetMode80x25(); 00723 case VIDEOMODE_EXTENDED_TEXT: 00724 return PcVideoSetMode80x50_80x43(); 00725 case VIDEOMODE_80X28: 00726 return PcVideoSetMode80x28(); 00727 case VIDEOMODE_80X30: 00728 return PcVideoSetMode80x30(); 00729 case VIDEOMODE_80X34: 00730 return PcVideoSetMode80x34(); 00731 case VIDEOMODE_80X43: 00732 return PcVideoSetMode80x43(); 00733 case VIDEOMODE_80X60: 00734 return PcVideoSetMode80x60(); 00735 } 00736 00737 if (0x12 == NewMode) 00738 { 00739 /* 640x480x16 */ 00740 PcVideoSetBiosMode((UCHAR)NewMode); 00741 WRITE_PORT_USHORT((USHORT*)0x03CE, 0x0F01); /* For some reason this is necessary? */ 00742 ScreenWidth = 640; 00743 ScreenHeight = 480; 00744 BytesPerScanLine = 80; 00745 BiosVideoMode = NewMode; 00746 DisplayMode = VideoGraphicsMode; 00747 00748 return TRUE; 00749 } 00750 else if (0x13 == NewMode) 00751 { 00752 /* 320x200x256 */ 00753 PcVideoSetBiosMode((UCHAR)NewMode); 00754 ScreenWidth = 320; 00755 ScreenHeight = 200; 00756 BytesPerScanLine = 320; 00757 BiosVideoMode = NewMode; 00758 DisplayMode = VideoGraphicsMode; 00759 00760 return TRUE; 00761 } 00762 else if (0x0108 <= NewMode && NewMode <= 0x010C) 00763 { 00764 /* VESA Text Mode */ 00765 if (! PcVideoVesaGetSVGAModeInformation(NewMode, &VesaVideoModeInformation)) 00766 { 00767 return FALSE; 00768 } 00769 00770 if (! PcVideoSetBiosVesaMode(NewMode)) 00771 { 00772 return FALSE; 00773 } 00774 00775 ScreenWidth = VesaVideoModeInformation.WidthInPixels; 00776 ScreenHeight = VesaVideoModeInformation.HeightInPixels; 00777 BytesPerScanLine = VesaVideoModeInformation.BytesPerScanLine; 00778 BiosVideoMode = NewMode; 00779 DisplayMode = VideoTextMode; 00780 VesaVideoMode = TRUE; 00781 00782 return TRUE; 00783 } 00784 else 00785 { 00786 /* VESA Graphics Mode */ 00787 if (! PcVideoVesaGetSVGAModeInformation(NewMode, &VesaVideoModeInformation)) 00788 { 00789 return FALSE; 00790 } 00791 00792 if (! PcVideoSetBiosVesaMode(NewMode)) 00793 { 00794 return FALSE; 00795 } 00796 00797 ScreenWidth = VesaVideoModeInformation.WidthInPixels; 00798 ScreenHeight = VesaVideoModeInformation.HeightInPixels; 00799 BytesPerScanLine = VesaVideoModeInformation.BytesPerScanLine; 00800 BiosVideoMode = NewMode; 00801 DisplayMode = VideoGraphicsMode; 00802 VesaVideoMode = TRUE; 00803 00804 return TRUE; 00805 } 00806 00807 return FALSE; 00808 } 00809 00810 static VOID 00811 PcVideoSetBlinkBit(BOOLEAN Enable) 00812 { 00813 REGS Regs; 00814 00815 /* Int 10h AX=1003h 00816 * VIDEO - TOGGLE INTENSITY/BLINKING BIT (Jr, PS, TANDY 1000, EGA, VGA) 00817 * 00818 * AX = 1003h 00819 * BL = new state 00820 * 00h background intensity enabled 00821 * 01h blink enabled 00822 * BH = 00h to avoid problems on some adapters 00823 * Return: 00824 * Nothing 00825 * 00826 * Note: although there is no function to get 00827 * the current status, bit 5 of 0040h:0065h 00828 * indicates the state. 00829 */ 00830 Regs.w.ax = 0x1003; 00831 Regs.w.bx = Enable ? 0x0001 : 0x0000; 00832 Int386(0x10, &Regs, &Regs); 00833 } 00834 00835 static VOID 00836 PcVideoSetMemoryBank(USHORT BankNumber) 00837 { 00838 REGS Regs; 00839 00840 if (CurrentMemoryBank != BankNumber) 00841 { 00842 /* Int 10h AX=4F05h 00843 * VESA SuperVGA BIOS - CPU VIDEO MEMORY CONTROL 00844 * 00845 * AX = 4F05h 00846 * BH = subfunction 00847 * 00h select video memory window 00848 * 01h get video memory window 00849 * DX = window address in video memory (in granularity units) 00850 * Return: 00851 * DX = window address in video memory (in gran. units) 00852 * BL = window number 00853 * 00h window A 00854 * 01h window B. 00855 * Return: 00856 * AL = 4Fh if function supported 00857 * AH = status 00858 * 00h successful 00859 * 01h failed 00860 */ 00861 Regs.w.ax = 0x4F05; 00862 Regs.w.bx = 0x0000; 00863 Regs.w.dx = BankNumber; 00864 Int386(0x10, &Regs, &Regs); 00865 00866 if (0x004F == Regs.w.ax) 00867 { 00868 CurrentMemoryBank = BankNumber; 00869 } 00870 } 00871 } 00872 00873 VIDEODISPLAYMODE 00874 PcVideoSetDisplayMode(char *DisplayModeName, BOOLEAN Init) 00875 { 00876 USHORT VideoMode = VIDEOMODE_NORMAL_TEXT; 00877 00878 if (NULL == DisplayModeName || '\0' == *DisplayModeName) 00879 { 00880 PcVideoSetBlinkBit(! Init); 00881 return DisplayMode; 00882 } 00883 00884 if (VIDEOCARD_CGA_OR_OTHER == PcVideoDetectVideoCard()) 00885 { 00886 TRACE("CGA or other display adapter detected.\n"); 00887 printf("CGA or other display adapter detected.\n"); 00888 printf("Using 80x25 text mode.\n"); 00889 VideoMode = VIDEOMODE_NORMAL_TEXT; 00890 } 00891 else if (VIDEOCARD_EGA == PcVideoDetectVideoCard()) 00892 { 00893 TRACE("EGA display adapter detected.\n"); 00894 printf("EGA display adapter detected.\n"); 00895 printf("Using 80x25 text mode.\n"); 00896 VideoMode = VIDEOMODE_NORMAL_TEXT; 00897 } 00898 else /* if (VIDEOCARD_VGA == PcVideoDetectVideoCard()) */ 00899 { 00900 TRACE("VGA display adapter detected.\n"); 00901 00902 if (0 == _stricmp(DisplayModeName, "NORMAL_VGA")) 00903 { 00904 VideoMode = VIDEOMODE_NORMAL_TEXT; 00905 } 00906 else if (0 == _stricmp(DisplayModeName, "EXTENDED_VGA")) 00907 { 00908 VideoMode = VIDEOMODE_EXTENDED_TEXT; 00909 } 00910 else 00911 { 00912 VideoMode = atoi(DisplayModeName); 00913 } 00914 } 00915 00916 if (! PcVideoSetMode(VideoMode)) 00917 { 00918 printf("Error: unable to set video display mode 0x%x\n", (int) VideoMode); 00919 printf("Defaulting to 80x25 text mode.\n"); 00920 printf("Press any key to continue.\n"); 00921 PcConsGetCh(); 00922 00923 PcVideoSetMode(VIDEOMODE_NORMAL_TEXT); 00924 } 00925 00926 PcVideoSetBlinkBit(! Init); 00927 00928 return DisplayMode; 00929 } 00930 00931 VOID 00932 PcVideoGetDisplaySize(PULONG Width, PULONG Height, PULONG Depth) 00933 { 00934 *Width = ScreenWidth; 00935 *Height = ScreenHeight; 00936 if (VideoGraphicsMode == DisplayMode && VesaVideoMode) 00937 { 00938 if (16 == VesaVideoModeInformation.BitsPerPixel) 00939 { 00940 /* 16-bit color modes give green an extra bit (5:6:5) 00941 * 15-bit color modes have just 5:5:5 for R:G:B */ 00942 *Depth = (6 == VesaVideoModeInformation.GreenMaskSize ? 16 : 15); 00943 } 00944 else 00945 { 00946 *Depth = VesaVideoModeInformation.BitsPerPixel; 00947 } 00948 } 00949 else 00950 { 00951 *Depth = 0; 00952 } 00953 } 00954 00955 ULONG 00956 PcVideoGetBufferSize(VOID) 00957 { 00958 return ScreenHeight * BytesPerScanLine; 00959 } 00960 00961 VOID 00962 PcVideoSetTextCursorPosition(UCHAR X, UCHAR Y) 00963 { 00964 REGS Regs; 00965 00966 /* Int 10h AH=02h 00967 * VIDEO - SET CURSOR POSITION 00968 * 00969 * AH = 02h 00970 * BH = page number 00971 * 0-3 in modes 2&3 00972 * 0-7 in modes 0&1 00973 * 0 in graphics modes 00974 * DH = row (00h is top) 00975 * DL = column (00h is left) 00976 * Return: 00977 * Nothing 00978 */ 00979 Regs.b.ah = 0x02; 00980 Regs.b.bh = 0x00; 00981 Regs.b.dh = Y; 00982 Regs.b.dl = X; 00983 Int386(0x10, &Regs, &Regs); 00984 } 00985 00986 VOID 00987 PcVideoHideShowTextCursor(BOOLEAN Show) 00988 { 00989 if (Show) 00990 { 00991 PcVideoDefineCursor(0x0D, 0x0E); 00992 } 00993 else 00994 { 00995 PcVideoDefineCursor(0x20, 0x00); 00996 } 00997 } 00998 00999 VOID 01000 PcVideoCopyOffScreenBufferToVRAM(PVOID Buffer) 01001 { 01002 USHORT BanksToCopy; 01003 ULONG BytesInLastBank; 01004 USHORT CurrentBank; 01005 ULONG BankSize; 01006 01007 /* PcVideoWaitForVerticalRetrace(); */ 01008 01009 /* Text mode (BIOS or VESA) */ 01010 if (VideoTextMode == DisplayMode) 01011 { 01012 RtlCopyMemory((PVOID) VIDEOTEXT_MEM_ADDRESS, Buffer, PcVideoGetBufferSize()); 01013 } 01014 /* VESA graphics mode */ 01015 else if (VideoGraphicsMode == DisplayMode && VesaVideoMode) 01016 { 01017 BankSize = VesaVideoModeInformation.WindowGranularity << 10; 01018 BanksToCopy = (USHORT)((VesaVideoModeInformation.HeightInPixels * VesaVideoModeInformation.BytesPerScanLine) / BankSize); 01019 BytesInLastBank = (VesaVideoModeInformation.HeightInPixels * VesaVideoModeInformation.BytesPerScanLine) % BankSize; 01020 01021 /* Copy all the banks but the last one because 01022 * it is probably a partial bank */ 01023 for (CurrentBank = 0; CurrentBank < BanksToCopy; CurrentBank++) 01024 { 01025 PcVideoSetMemoryBank(CurrentBank); 01026 RtlCopyMemory((PVOID) VIDEOVGA_MEM_ADDRESS, (char *) Buffer + CurrentBank * BankSize, BankSize); 01027 } 01028 01029 /* Copy the remaining bytes into the last bank */ 01030 PcVideoSetMemoryBank(CurrentBank); 01031 RtlCopyMemory((PVOID)VIDEOVGA_MEM_ADDRESS, (char *) Buffer + CurrentBank * BankSize, BytesInLastBank); 01032 } 01033 /* BIOS graphics mode */ 01034 else 01035 { 01036 UNIMPLEMENTED; 01037 } 01038 } 01039 01040 VOID 01041 PcVideoClearScreen(UCHAR Attr) 01042 { 01043 USHORT AttrChar; 01044 USHORT *BufPtr; 01045 01046 AttrChar = ((USHORT) Attr << 8) | ' '; 01047 for (BufPtr = (USHORT *) VIDEOTEXT_MEM_ADDRESS; 01048 BufPtr < (USHORT *) (VIDEOTEXT_MEM_ADDRESS + VIDEOTEXT_MEM_SIZE); 01049 BufPtr++) 01050 { 01051 *BufPtr = AttrChar; 01052 } 01053 } 01054 01055 VOID 01056 PcVideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y) 01057 { 01058 USHORT *BufPtr; 01059 01060 BufPtr = (USHORT *) (ULONG_PTR)(VIDEOTEXT_MEM_ADDRESS + Y * BytesPerScanLine + X * 2); 01061 *BufPtr = ((USHORT) Attr << 8) | (Ch & 0xff); 01062 } 01063 01064 BOOLEAN 01065 PcVideoIsPaletteFixed(VOID) 01066 { 01067 return FALSE; 01068 } 01069 01070 VOID 01071 PcVideoSetPaletteColor(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue) 01072 { 01073 WRITE_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_WRITE, Color); 01074 WRITE_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA, Red); 01075 WRITE_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA, Green); 01076 WRITE_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA, Blue); 01077 } 01078 01079 VOID 01080 PcVideoGetPaletteColor(UCHAR Color, UCHAR* Red, UCHAR* Green, UCHAR* Blue) 01081 { 01082 WRITE_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_READ, Color); 01083 *Red = READ_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA); 01084 *Green = READ_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA); 01085 *Blue = READ_PORT_UCHAR((UCHAR*) VIDEOPORT_PALETTE_DATA); 01086 } 01087 01088 VOID 01089 PcVideoSync(VOID) 01090 { 01091 while (1 == (READ_PORT_UCHAR((UCHAR*)VIDEOPORT_VERTICAL_RETRACE) & 0x08)) 01092 { 01093 /* 01094 * Keep reading the port until bit 3 is clear 01095 * This waits for the current retrace to end and 01096 * we can catch the next one so we know we are 01097 * getting a full retrace. 01098 */ 01099 } 01100 01101 while (0 == (READ_PORT_UCHAR((UCHAR*)VIDEOPORT_VERTICAL_RETRACE) & 0x08)) 01102 { 01103 /* 01104 * Keep reading the port until bit 3 is set 01105 * Now that we know we aren't doing a vertical 01106 * retrace we need to wait for the next one. 01107 */ 01108 } 01109 } 01110 01111 VOID 01112 PcVideoPrepareForReactOS(IN BOOLEAN Setup) 01113 { 01114 if (Setup) 01115 { 01116 PcVideoSetMode80x50_80x43(); 01117 } 01118 else 01119 { 01120 PcVideoSetBiosMode(0x12); 01121 } 01122 PcVideoHideShowTextCursor(FALSE); 01123 } 01124 01125 /* EOF */ Generated on Fri May 25 2012 04:17:10 for ReactOS by
1.7.6.1
|