📄 vbe.c
字号:
/* * Copyright (C) 2001, Michael Hilsdale. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* Instructions to use this code * ============================= * * 1. call InitVesa() * 2. receive a good mode number from ChooseVESA() * 3. set that mode number using SetConsoleMode(bi, consoleMode) * which will populate the ConsoleInfo struct inside BootInfo bi * */#include <eros/target.h>#include <eros/i486/io.h>#include <kerninc/BootInfo.h>#include "boot.h"#include "boot-asm.h"#include "debug.h"/*************************************************************************//* Preferences *//* =========== */#define FB_PREF 0 /* Preference to use linear fb (1, default) * or windowed fb (0) * NOTE: This is only a preference. If the * prefered fb type is not available, the * other type will be used. *//* Mode Preferences *//* Refer to comments in ChooseVesa() */#define maxXpref 1024#define maxYpref 768#define maxBPPpref 32/*************************************************************************/#define MAX_MODES 29 /* Reasonable guess as to max number * of modes to expect. */#define BELL 7/* Display Window Control */#define SETWIN 0#define GETWIN 1#define WINA 0#define WINB 1/* Environment Info */#define UNKNOWN 0#define VMWARE 1#define VMWARE_MODE 0x4022uint8_t environment;uint8_t VESAinit = 0; /* VESA not initialized */uint8_t origMode;/* Supported mode information */uint8_t numModesSupported = 0;uint16_t modeList[MAX_MODES];/* Mode state variables */uint8_t curBank;uint8_t bankShift;/* This is what we want. *//*************************/uint8_t *frameBufferBase;/*************************/struct Vbe3Block { /* This struct is VESA 3.0 compliant. * The total size of this struct is 512 bytes. */ char VESASignature[4]; uint16_t VESAVersion; char *OEMStringPtr; uint32_t Capabilities; uint16_t *VideoModePtr; uint16_t TotalMemory; uint16_t OEMSoftwareRev; char *OEMVendorNamePtr; char *OEMProductNamePtr; char *OEMProductRevPtr; char reserved[222]; char reservedOEM[256];} __attribute((packed));struct Mode{ short int number:9; short int reserved:2; short int refresh:1; short int reserved2:2; short int linearmodel:1; short int cleardisplay:1;};struct ModeInfoBlock{ /* This struct is VBE 3.0 compliant */ uint16_t modeAttributes; uint8_t WinAAttributes; uint8_t WinBAttributes; uint16_t WinGranularity; uint16_t WinSize; uint16_t WinASegment; uint16_t WinBSegment; uint32_t WinFuncPtr; uint16_t BytesPerScanLine; uint16_t XResolution; uint16_t YResolution; uint8_t XCharSize; uint8_t YCharSize; uint8_t NumberOfPlanes; uint8_t BitsPerPixel; uint8_t NumberOfBanks; uint8_t MemoryModel; uint8_t BankSize; uint8_t NumberOfImagePages; uint8_t reserved; uint8_t RedMaskSize; uint8_t RedFieldPosition; uint8_t GreenMaskSize; uint8_t GreenFieldPosition; uint8_t BlueMaskSize; uint8_t BlueFieldPosition; uint8_t RsvdMaskSize; uint8_t RsvdFieldPosition; uint8_t DirectColorModeInfo; uint32_t PhysBasePtr; /* physical address for flat memory frame buffer */ uint32_t reserved2; /* VBE 2.0 spec uses this for *OffScreenMemOffset */ uint16_t reserved3; /* VBE 2.0 spec uses this for OffScreenMemSize */ uint16_t LinBytesPerScanLine; uint8_t BnkNumberOfImagePages; uint8_t LinNumberOfImagePages; uint8_t LinRedMaskSize; uint8_t LinRedFieldPosition; uint8_t LinGreenMaskSize; uint8_t LinGreenFieldPosition; uint8_t LinBlueMaskSize; uint8_t LinBlueFieldPosition; uint8_t LinRsvdMaskSize; uint8_t LinRsvdFieldPosition; uint32_t MaxPixelClock; uint8_t reserved4[189]; /* Shouldn't this be 190? The spec says 189. */} __attribute((packed));struct CRTCInfo{ uint16_t HorizontalTotal; uint16_t HorizontalSyncStart; uint16_t HorizontalSyncEnd; uint16_t VerticalTotal; uint16_t VerticalSyncStart; uint16_t VerticalSyncEnd; uint8_t flags; uint32_t PixelClock; uint16_t RefreshRate; char Reserved[40];};struct ModeAttributes{ /* ISSUE: these need to be defined using uint16_t for alignment reasons. */ uint16_t hw:1; uint16_t resv:1; uint16_t tty:1; uint16_t color:1; uint16_t graphics:1; uint16_t notvga:1; uint16_t nowin:1; uint16_t linfb:1; uint16_t dbscan:1; uint16_t ilace:1; uint16_t tpbuf:1; uint16_t stereo:1; uint16_t dual:1; uint16_t resv2:3;};enum WinAttributes { wa_relocatable = 0x1u, wa_readable = 0x2u, wa_writeable = 0x4u,} ;enum MemModels { mm_Text = 0, mm_CGA = 1, mm_Hercules = 2, mm_Planar = 3, mm_PackedPixel = 4, mm_NonChain = 5, /* non-chain 4, 256 color */ mm_DirectColor = 6, mm_YUV = 7, /* 0x08-0x0f reserved for future VESA standards */ /* 0x10-0xff reserved for OEM-defined modes */};/* Global structs */struct Vbe3Block Vbe3InfoBlock;struct ModeInfoBlock modeInfoBlock;struct ModeAttributes modeAttributes;struct CRTCInfo CRTCInfoBlock;/* External functions *//* Located in hibios.S */#define AsmGetVgaMode() GetDisplayMode()#define AsmSetVgaMode(x) SetDisplayMode(x)extern unsigned SetDisplayMode(uint8_t mode);/* Located in vesa.S */extern unsigned AsmGetVbeControllerInfo(struct Vbe3Block *);extern unsigned AsmGetVbeModeInfo(uint16_t mode, struct ModeInfoBlock *);extern unsigned AsmSetVbeMode(uint16_t mode, struct CRTCInfo *);extern unsigned AsmReturnCurrentVbeMode();extern unsigned AsmDisplayWindowControl(uint8_t getset, uint8_t AorB, uint16_t winNum);/* Local functions */void getVbe3Info(); /* uses assembly magic */void setVbe3Info();uint8_t findEnvironment();#if 0void printVbe3Info();void printCapabilities();#endifvoid printVideoModes();void getVideoModes();void printCurrentModeInfo();void getModeInfo(const uint16_t modeNumber); /* uses assembly magic */uint8_t setMode(const uint16_t modeNumber); /* uses assembly magic *//* Issue: The entire #define mechanism is actually quite disgusting. No. Even more disgusting than *that*. */#define handleReturn(s) moreHelpfulHandleReturn(#s, s)uint8_t moreHelpfulHandleReturn(const char * str, const uint16_t retVal);void testGraphics();void ChezPaul();void vertline();void horizline();void dabble(); /* pretty pattern */void putPixel(const uint16_t x, const uint16_t y, const uint32_t color);void setBank(const uint16_t bank); /* uses assembly magic */uint16_t getCurrentMode(); /* uses assembly magic */void line(int x1, int y1, int x2, int y2, int color); /* copied */void drawMoire(); /* copied */void test();void SetConsoleMode(BootInfo *bi, uint32_t mode);/*************************************************************************/unsignedGetVbeControllerInfo(struct Vbe3Block *info){ unsigned result = AsmGetVbeControllerInfo(info);#define REAL2PA(x) \ ( ((((unsigned long)(x)) >> 12) & 0xffff0u) + \ (((unsigned long) (x)) & 0xffffu) )#define REAL2BOOT(x, ty) PA2BOOT( REAL2PA(x), ty) /* The Vbe3InfoBlock contains various pointers. Because we used the * int 0x10 interface, the returned pointers are real mode pointers * of the form 0xsssspppp, where ssss is the segment value. We need * to convert these pointer into values that can be used directly * from the bootstrap code.... */ info->VideoModePtr = REAL2BOOT(info->VideoModePtr, uint16_t *); info->OEMStringPtr = REAL2BOOT(info->OEMStringPtr, char*); info->OEMVendorNamePtr = REAL2BOOT(info->OEMVendorNamePtr, char*); info->OEMProductNamePtr = REAL2BOOT(info->OEMProductNamePtr, char *); info->OEMProductRevPtr = REAL2BOOT(info->OEMProductRevPtr, char *); return result;}uint8_tInitVESA(){ char sig[5]; printf("Starting VESA support..."); origMode = AsmGetVgaMode(); /* get ready to tell card to use VESA support */ memset(&Vbe3InfoBlock, 0, sizeof(Vbe3InfoBlock)); strcpy(Vbe3InfoBlock.VESASignature,"VBE2"); /* REQUIRED EVEN WHEN NOT DEBUGGING */ /* query card for VESA information */ getVbe3Info(); /* test for VESA compliance */ memcpy(sig, Vbe3InfoBlock.VESASignature, 4); sig[4] = 0; if(strcmp(sig,"VESA")) { printf("Failed!\n"); return 1; /* no VESA support */ } else printf("Successful!\n"); VESAinit = 1; /* VESA is supported and initialized */ environment = findEnvironment(); return 0;}uint32_tChooseVESA(){ uint8_t a; uint16_t b; struct { uint16_t mode; uint16_t x; uint16_t y; uint16_t bpp; } best; best.mode = 0; best.x = 0; best.y = 0; best.bpp = 0; if(!VESAinit) { printf("ERROR: Either VESA was not initialized or is not supported.\nAborting...."); waitkbd(); printf("\n"); return 0; } /*printVbe3Info(); waitkbd();*/ /*testGraphics();*/ /* Find a suitable mode */ /* Current logic: Find the highest possible supported resolution * that is less than or equal to the prefered resolution. * If none is found, this function will return 0, and a text * mode should be used instead of a graphics mode. * Caveat: If the prefered bit depth is lower than those * available, then no mode will be chosen. (For example, if you * want 1024x768x24, but only 1024x768x32 is available, no * graphics mode will be selected.) */ for(a = 0; a < numModesSupported; a++) { getModeInfo(modeList[a]); if(modeInfoBlock.XResolution <= maxXpref && modeInfoBlock.XResolution >= best.x) if(modeInfoBlock.YResolution <= maxYpref && modeInfoBlock.YResolution >= best.y) if(modeInfoBlock.BitsPerPixel <= maxBPPpref && modeInfoBlock.BitsPerPixel >= best.bpp) { /* FIXME: * If no linfb available, don't use graphic mode since console doesn't support it yet. */#if 0 if(modeAttributes.linfb) {#endif best.mode = modeList[a]; best.x = modeInfoBlock.XResolution; best.y = modeInfoBlock.YResolution; best.bpp = modeInfoBlock.BitsPerPixel;#if 0 }#endif } } printf("modes supported: %d\n", numModesSupported); for(b = 0; b < numModesSupported; b++) { getModeInfo(modeList[b]); printf("0x%x: %4d x %4d x %2d ", modeList[b], modeInfoBlock.XResolution, modeInfoBlock.YResolution, modeInfoBlock.BitsPerPixel); printf((modeAttributes.linfb ? "linfb" : "windowed")); printf("\n"); } getModeInfo(best.mode); if(best.mode) { printf("Will use graphics mode 0x%x: %4d x %4d x %2d\n", best.mode, best.x, best.y, best.bpp); printCurrentModeInfo(); waitkbd(); } /* DEBUG info: */ /* getModeInfo(best.mode); printf("Desired video mode:\n"); printf(" X : %d\n",maxXpref); printf(" Y : %d\n",maxYpref); printf(" BPP : %d\n\n",maxBPPpref); printf("Best video mode found:\n"); printf(" Mode: 0x%x\n",best.mode); printf(" X : %d\n",best.x); printf(" Y : %d\n",best.y); printf(" BPP : %d\n\n",best.bpp); printCurrentModeInfo(); waitkbd(); */ return best.mode;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -