ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pcvideo.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.