Page 1 of 1
[SOLVED] VESA and Bochs
Posted: Tue Aug 11, 2009 2:12 am
by AlfaOmega08
Hi, I finally got a Virtual 8086 monitor working, and now I'm trying to switch to a graphic mode. I want higher resolution than VGA so I'm working on VESA. After the kernel initialization, I check for the presence of VESA on the system with INT 0x10 AX = 0x4F00. Then I try to detect the best resolution available on the system between modes 0x113, 0x115, 0x116, 0x118, 0x119, 0x11B (800x600, 1024x768, 1280x1024 at 16bpp or 32bpp), using INT 0x10 AX = 0x4F01 and checking for the bits 0, 4 and 5 of the mode attribute to see if it can be used. Found the mode I switch to it using INT 0x10 AX = 0x4F02. This works well on my desktop hardware and on virtualbox but it doesn't on bochs or my eeePC. Bochs gives always attribute = 0 for any of the modes but if I try to force the switch it change the mode but won't let me writing pixels.
May I have misconfigured bochs? Or is a code problem?
Re: VESA and Bochs
Posted: Tue Aug 11, 2009 2:35 am
by f2
I never had any problems with Bochs with VESA modes. If Bochs was misconfigured, INT 0x10 says that there is no VESA support.
I think there's an error in your code.
Re: VESA and Bochs
Posted: Tue Aug 11, 2009 3:32 am
by AlfaOmega08
Uhm... now it doesn't work neither on real hardware... Here is my code
Code: Select all
struct VESAHeader {
char signature[4];
short version;
short oemString[2];
unsigned char capabilities[4];
short videomodes[2];
short totalMemory;
};
struct VESAModeInfo {
word attributes;
byte winA,winB;
word granularity;
word winsize;
word segmentA, segmentB;
dword realFctPtr;
word pitch;
word Xres, Yres;
byte Wchar, Ychar, planes, bpp, banks;
byte memory_model, bank_size, image_pages;
byte reserved0;
byte red_mask, red_position;
byte green_mask, green_position;
byte blue_mask, blue_position;
byte rsv_mask, rsv_position;
byte directcolor_attributes;
dword physbase;
} __attribute__ ((packed));
void setbank(int n) {
struct regs regs;
regs.eax = 0x4F05;
regs.ebx = 0;
regs.edx = n;
v86_int(0x10, ®s);
}
int curBank = 0;
void PutPixel(int x, int y, dword color, dword gran, dword max, dword bpp) {
int addr = y * max + x;
int banksize = gran * max;
int bnum = addr / banksize;
int boff = addr % banksize;
if (bnum != curBank) {
setbank(bnum);
curBank = bnum;
}
if (bpp == 16) {
word *ptr = (word *) (0xC00A0000 + boff * 2);
*ptr = color & 0xFFFFFF;
} else if (bpp == 24) {
byte *ptr = (byte *) (0xC00A0000 + boff * 3);
ptr[0] = color & 0xFF;
ptr[1] = color >> 8 & 0xFF;
ptr[2] = color >> 16 & 0xFF;
} else if (bpp == 32) {
dword *ptr = (dword *) (0xC00A0000 + boff * 4);
*ptr = color;
}
}
void vesa_init() {
struct regs regs;
// Read the vesa header
regs.eax = 0x4F00;
regs.es = 0;
regs.edi = 0x2000;
v86_int(0x10, ®s);
if (regs.eax != 0x004F) {
panic("VESA is not present on this system\n");
}
struct VESAHeader *vbe = (struct VESAHeader *) 0xC0002000;
if (strncmp(vbe->signature, "VESA", 4)) {
panic("Wrong VESA signature\n");
}
word Modes[6] = { 0x113, 0x115, 0x116, 0x118, 0x119, 0x11B };
int i, best = -1;
for (i = 0; i < 6; i++) {
// Get Mode informations
regs.eax = 0x4F01;
regs.ebx = Modes[i];
regs.es = 0;
regs.edi = 0x3000;
v86_int(0x10, ®s);
struct VESAModeInfo *tmp = (struct VESAModeInfo *) 0xC0003000;
if (tmp->attributes & 0x19 == 0x19) {
kprintf("Mode %04X, %dx%dx%d detected\n", Modes[i], tmp->Xres, tmp->Yres, tmp->bpp);
best = Modes[i];
} else {
kprintf("Bad mode %04X attr %d\n", Modes[i], tmp->attributes);
}
}
if (best == -1) {
panic("Unable to find an available VESA mode");
}
kprintf("Best mode found: %04X", Modes[best]);
struct VESAModeInfo *tmp = (struct VESAModeInfo *) 0xC0003000;
// Set video mode
regs.eax = 0x4F02;
regs.ebx = Modes[best];
v86_int(0x10, ®s);
int gran = tmp->granularity;
int maxX = tmp->Xres;
int maxY = tmp->Yres;
int bpp = tmp->bpp;
for (i = 0; i < maxX; i++) {
int j;
for (j = 0; j < maxY; j++) {
PutPixel(i, j, 0xFFFFFFFF, gran, maxX, bpp);
}
}
}
please help me
Re: VESA and Bochs
Posted: Tue Aug 11, 2009 3:37 am
by giszo
AlfaOmega08 wrote:please help me
What about using packed attribute on the VESA structs?
Re: VESA and Bochs
Posted: Tue Aug 11, 2009 3:42 am
by AlfaOmega08
well, the packed attribute, may be one of the causes, but it hasn't solved the problem.
thanks for the trying
Re: VESA and Bochs
Posted: Tue Aug 11, 2009 3:55 am
by f2
Code: Select all
best = Modes[i];
...
regs.ebx = Modes[best];
Perhaps the problem is here...
Should be:
Another thing:
AlfaOmega08 wrote:and checking for the bits 0, 4 and 5
0x19 -> 11001 -> bit 0, 3 and 4 are set here.
Note: if you use banks, you shouldn't check if bit 5 is set.
Re: VESA and Bochs
Posted: Tue Aug 11, 2009 4:32 am
by AlfaOmega08
thank you tommy the first error was the cause for witch the code didn't work anymore on real hardware. However I still have problems anywhere else...
I prefer to use lfb instead of banks so as suggested on the wiki I check for bits 0x90 of the attribute instead of 0x19. I noticed that Bochs returns as resolutions for any of the modes 0x0 at 0 bpp with attribute 0. Isn't that nice?
However now the code is:
Code: Select all
struct VESAHeader {
char signature[4];
short version;
short oemString[2];
unsigned char capabilities[4];
short videomodes[2];
short totalMemory;
} __attribute__ ((packed));
struct VESAModeInfo {
word attributes;
byte winA,winB;
word granularity;
word winsize;
word segmentA, segmentB;
dword realFctPtr;
word pitch;
word Xres, Yres;
byte Wchar, Ychar, planes, bpp, banks;
byte memory_model, bank_size, image_pages;
byte reserved0;
byte red_mask, red_position;
byte green_mask, green_position;
byte blue_mask, blue_position;
byte rsv_mask, rsv_position;
byte directcolor_attributes;
dword physbase;
} __attribute__ ((packed));
void PutPixel(int x, int y, dword color, dword max, dword bpp, dword buff) {
int addr = y * max + x;
if (bpp == 16) {
word *ptr = (word *) (0xC00A0000 + addr * 2);
*ptr = color & 0xFFFFFF;
} else if (bpp == 24) {
byte *ptr = (byte *) (0xC00A0000 + addr * 3);
ptr[0] = color & 0xFF;
ptr[1] = color >> 8 & 0xFF;
ptr[2] = color >> 16 & 0xFF;
} else if (bpp == 32) {
dword *ptr = (dword *) (0xC00A0000 + addr * 4);
*ptr = color;
}
}
void vesa_init() {
struct regs regs;
// Read the vesa header
regs.eax = 0x4F00;
regs.es = 0;
regs.edi = 0x2000;
v86_int(0x10, ®s);
if (regs.eax != 0x004F) {
panic("VESA is not present on this system\n");
}
struct VESAHeader *vbe = (struct VESAHeader *) 0xC0002000;
if (strncmp(vbe->signature, "VESA", 4)) {
panic("Wrong VESA signature\n");
}
word Modes[6] = { 0x113, 0x115, 0x116, 0x118, 0x119, 0x11B };
int i, best = -1;
for (i = 0; i < 6; i++) {
// Get Mode informations
regs.eax = 0x4F01;
regs.ebx = Modes[i];
regs.es = 0;
regs.edi = 0x3000;
v86_int(0x10, ®s);
struct VESAModeInfo *tmp = (struct VESAModeInfo *) 0xC0003000;
if (tmp->attributes & 0x90 == 0x90) {
kprintf("Mode %04X, %dx%dx%d detected\n", Modes[i], tmp->Xres, tmp->Yres, tmp->bpp);
best = Modes[i];
} else {
kprintf("Bad mode %04X attr %d, %dx%d\n", Modes[i], tmp->attributes, tmp->Xres, tmp->Yres);
}
}
if (best == -1) {
panic("Unable to find an available VESA mode");
}
kprintf("Best mode found: %04X", best);
struct VESAModeInfo *tmp = (struct VESAModeInfo *) 0xC0003000;
// Set video mode
regs.eax = 0x4F02;
regs.ebx = best;
v86_int(0x10, ®s);
int buff = tmp->physbase;
int maxX = tmp->Xres;
int maxY = tmp->Yres;
int bpp = tmp->bpp;
for (i = 0; i < maxX; i++) {
int j;
for (j = 0; j < maxY; j++) {
PutPixel(i, j, 0xFFFFFFFF, maxX, bpp, buff);
}
}
}
Re: VESA and Bochs
Posted: Thu Aug 13, 2009 1:38 pm
by AlfaOmega08
OK, while JamesM is on the road of 2D Graphic acceleration
, I am still unable to use VESA. Something strange is happenin in my code. I changed all the extensions from .c to .cpp and did the needed changes to the code to be compiled as c++ (casting void * for maths and for malloc
s, changing char * to const char * etc...) and the code shown before just does its work. On bochs as well as on real hardware. The strange thing is that if I put a "while (1);" just before the mode switch interrupt, the code doesn't find any good VESA mode on bochs anymore. If I remove that while (1) the mode is found and switched
. May this be a G++/GCC bug?
Re: VESA and Bochs
Posted: Thu Aug 13, 2009 2:02 pm
by tantrikwizard
AlfaOmega08 wrote:May this be a G++/GCC bug?
highly unlikely. VESA works fine on my bochs build. Make sure you have vga: extension=vbe in the bochsrc It might not be related to your problem but I think it's required to use VBE. Bochs does not fully implement all the VBE extensions but it does implement the stuff you're trying to use.
Re: VESA and Bochs
Posted: Thu Aug 13, 2009 2:49 pm
by AlfaOmega08
Bochs has VBE extension enabled. I have vga: extension=vbe in bochsrc.txt. As I said the code works until I insert a while(1) after the mode search. If I insert a "while(1)" line the code stops working
Re: VESA and Bochs
Posted: Thu Aug 13, 2009 4:04 pm
by AlfaOmega08
Got it!!!
// Get Mode informations
regs.eax = 0x4F01;
regs.ebx = Modes;
regs.es = 0;
regs.edi = 0x3000;
v86_int(0x10, ®s);
Reading the RBIL I discovered that the mode have to be set in ecx, not in ebx... Now I have to understand why did I use ebx
Re: VESA and Bochs
Posted: Thu Aug 13, 2009 6:11 pm
by tantrikwizard
AlfaOmega08 wrote:Got it!!!
Why not read the docs? The spec fully outlines the register formats and interrupts.