vbe functions in protected mode
-
- Member
- Posts: 37
- Joined: Sat Apr 11, 2015 9:37 am
vbe functions in protected mode
i am studying the vbe functions, and i found that calling the 00H function requires putting the vbeinfoblock's address in ES:DS, but, my kernel is in protected mode and the structure that i declared is also on "high" memory.
how can i pass the struct's address in segment registers, as it can only address 64 kb of memory ??
if i can't do that, how can i use the func 00H in Vbe 2.0 in protected mode ??
i am NOT using a v8086 handler, but i can safely jump to real mode and execute interrupts there.
--- Thanx in advance,
WarMachine
how can i pass the struct's address in segment registers, as it can only address 64 kb of memory ??
if i can't do that, how can i use the func 00H in Vbe 2.0 in protected mode ??
i am NOT using a v8086 handler, but i can safely jump to real mode and execute interrupts there.
--- Thanx in advance,
WarMachine
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: vbe functions in protected mode
Not quite true.segment registers [...] can only address 64 kb of memory
Since you're in real mode - and you have to copy code and register info there, what prevents you from copying a local data block there back into higher memory addresses? There's not that much data anyway.
Re: vbe functions in protected mode
Hi,
For using VBE's real mode interface ("int 0x10") there's at least 3 more options:
For the first case (using real mode) you must put the structure somewhere that real mode can access. This doesn't mean you can't move it before or after if you want it to be somewhere above 0x00100000 instead.
Cheers,
Brendan
There's 3 different cases:snasim2002 wrote:i am studying the vbe functions, and i found that calling the 00H function requires putting the vbeinfoblock's address in ES:DS, but, my kernel is in protected mode and the structure that i declared is also on "high" memory.
how can i pass the struct's address in segment registers, as it can only address 64 kb of memory ??
if i can't do that, how can i use the func 00H in Vbe 2.0 in protected mode ??
- Using VBE's real mode interface ("int 0x10")
- Using VBE 2.0's protected mode interface
- Using VBE 3.0's protected mode interface
For using VBE's real mode interface ("int 0x10") there's at least 3 more options:
- Using real mode
- Using virtual8086 mode
- Using emulation (e.g. "machine code interpreter")
For the first case (using real mode) you must put the structure somewhere that real mode can access. This doesn't mean you can't move it before or after if you want it to be somewhere above 0x00100000 instead.
The only case where it's safe to switch to real mode is before the OS takes control of the hardware (and changes PIC/IO APIC, sets up timers, changes the state of devices, etc). If you're setting up a video mode during boot (the only case where its safe to switch to real mode), then it makes far more sense to do it before your kernel is loaded/started (e.g. in boot code, while you're already in real mode and/or switching between real mode and protected mode). There's no good reason to clutter up the kernel with "only used once during boot" initialisation code (especially when that code depends on whether the firmware happens to be BIOS or UEFI or something else).snasim2002 wrote:i am NOT using a v8086 handler, but i can safely jump to real mode and execute interrupts there.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
-
- Member
- Posts: 37
- Joined: Sat Apr 11, 2015 9:37 am
Re: vbe functions in protected mode
I placed the VbeInfoBlock at 0x2000, and the modeinfoblock at 0x3000. I created a pointer to a struct that points to their respective structure.
Now i can easily access the structures through the pointers.
--Now, a new issue arises.. --
i am using mode 0x103. (800x600, 8 bpp, 256 colors)
how can i plot a pixel at a specified location on screen ?? it says that the linear framebuffer starts at 0xFD000000.
Also, i saw something called "banking" . What's that ?
Now i can easily access the structures through the pointers.
--Now, a new issue arises.. --
i am using mode 0x103. (800x600, 8 bpp, 256 colors)
how can i plot a pixel at a specified location on screen ?? it says that the linear framebuffer starts at 0xFD000000.
Also, i saw something called "banking" . What's that ?
Re: vbe functions in protected mode
Hi,
The first way is called "windowed mode" where you typically have 2 little "display memory windows" (e.g. maybe one at 0x0000A0000 and another at 0x0000B0000 in the legacy VGA area), where you tell the video card which part of display memory it should put in each window. In this case, to plot a pixel you determine the location of the pixel in display memory, then tell the video card to make that area appear in one of the windows (note: one that can be written to), then figure out where the pixel would actually be within the window ("offset in display memory - start of bank"), then write to that address in the window. Note that for some cases (e.g. 24-bpp modes) a pixel can be split across different banks (e.g. 2 bytes in one bank and the other byte in a different bank); and (when using paging) you'd map the "windows" wherever you like in your virtual address space (and use the "virtual address I mapped the window" and not its physical address). Obviously this is a massive pain in the neck (and only really exists for compatibility with real mode software).
The other way is is called "linear frame buffer" (LFB). In this case, to plot a pixel you determine the location of the pixel in display memory, add the "address of display memory" to that, then write the pixel to that address. Note that (when using paging) you'd map the linear frame buffer wherever you like in your virtual address space (and use the "virtual address I mapped the display memory" and not its physical address).
For determining the offset of a pixel in display memory, you'd do something like "offset = Y * bytes_per_line + X * bytes_per_pixel". Don't do "offset = Y * horizontal_resolution + X) * bytes_per_pixel" because this is broken and wrong (there can be invisible padding between lines).
For both cases; don't write pixels to display memory at all. It's slow and causes problems (tearing artefacts, etc). Instead you want (at least) one buffer in RAM where you do all the drawing; and when you're finished you copy ("blit") data (or maybe just data that is different) from your buffer in RAM to display memory. For bank switched/windowed modes this also avoids a huge amount of bank switching (and solves the "pixel in 2 different banks" mess).
The main problem with "windowed mode" is that you have to use a VBE function to change the bank, and if you want to stay in protected mode that ends up being more trouble than it's worth. Fortunately almost all video cards support "linear frame buffer" and you can just refuse to use "windowed mode" and pretend it never existed (and for a "worst case fallback" that will probably never happen, if the video card is so old and crusty that it doesn't support LFB then you can still use 320*200 because all pixels fit in one bank).
The other problem with "windowed mode" is that it can't work for multiple monitors because there's only one legacy VGA area; which is possibly part of why it's not supported by UEFI (and why it should be considered "deprecated" for any new OS).
Cheers,
Brendan
There's 2 different ways to access display memory.snasim2002 wrote:i am using mode 0x103. (800x600, 8 bpp, 256 colors)
how can i plot a pixel at a specified location on screen ?? it says that the linear framebuffer starts at 0xFD000000.
Also, i saw something called "banking" . What's that ?
The first way is called "windowed mode" where you typically have 2 little "display memory windows" (e.g. maybe one at 0x0000A0000 and another at 0x0000B0000 in the legacy VGA area), where you tell the video card which part of display memory it should put in each window. In this case, to plot a pixel you determine the location of the pixel in display memory, then tell the video card to make that area appear in one of the windows (note: one that can be written to), then figure out where the pixel would actually be within the window ("offset in display memory - start of bank"), then write to that address in the window. Note that for some cases (e.g. 24-bpp modes) a pixel can be split across different banks (e.g. 2 bytes in one bank and the other byte in a different bank); and (when using paging) you'd map the "windows" wherever you like in your virtual address space (and use the "virtual address I mapped the window" and not its physical address). Obviously this is a massive pain in the neck (and only really exists for compatibility with real mode software).
The other way is is called "linear frame buffer" (LFB). In this case, to plot a pixel you determine the location of the pixel in display memory, add the "address of display memory" to that, then write the pixel to that address. Note that (when using paging) you'd map the linear frame buffer wherever you like in your virtual address space (and use the "virtual address I mapped the display memory" and not its physical address).
For determining the offset of a pixel in display memory, you'd do something like "offset = Y * bytes_per_line + X * bytes_per_pixel". Don't do "offset = Y * horizontal_resolution + X) * bytes_per_pixel" because this is broken and wrong (there can be invisible padding between lines).
For both cases; don't write pixels to display memory at all. It's slow and causes problems (tearing artefacts, etc). Instead you want (at least) one buffer in RAM where you do all the drawing; and when you're finished you copy ("blit") data (or maybe just data that is different) from your buffer in RAM to display memory. For bank switched/windowed modes this also avoids a huge amount of bank switching (and solves the "pixel in 2 different banks" mess).
The main problem with "windowed mode" is that you have to use a VBE function to change the bank, and if you want to stay in protected mode that ends up being more trouble than it's worth. Fortunately almost all video cards support "linear frame buffer" and you can just refuse to use "windowed mode" and pretend it never existed (and for a "worst case fallback" that will probably never happen, if the video card is so old and crusty that it doesn't support LFB then you can still use 320*200 because all pixels fit in one bank).
The other problem with "windowed mode" is that it can't work for multiple monitors because there's only one legacy VGA area; which is possibly part of why it's not supported by UEFI (and why it should be considered "deprecated" for any new OS).
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re: vbe functions in protected mode
Banking/windows/granularity is what you have to deal with when you don't enable the linear frame buffer or when it's not available. It's the old/original way of accessing the video memory from 16-bit real and protected mode where segmentation limits you to accessing at most 64KB of memory at a time. The 64KB at physical address 0xA0000 would be a window into the video memory. By calling dedicated VESA BIOS functions you can project this window onto different parts of the entire video memory and thus gain access to all of it. Beware, the window size supported by your card can be smaller than 64KB and that there can be/are two windows, AFAIR, one for reading and one for writing. You should really read the documentation at this point instead of asking questions, which will lead to even more questions, answers to all of which are in the doc and we'd be just doing reading for you.
-
- Member
- Posts: 37
- Joined: Sat Apr 11, 2015 9:37 am
Re: vbe functions in protected mode
I have programmed in mode 0x13 before, and in that, I could easily plot a pixel using:
So, in vbe, how can i determine the color ?? is there any fixed pallete as in mode 0x13 ??
Code: Select all
VGA[offset] = color
Re: vbe functions in protected mode
There's a palette in 8bpp modes. Chances are it's the same as in mode 0x13 and programmable the same way, however, the latter part and colors beyond 15 (white) aren't guaranteed.snasim2002 wrote:I have programmed in mode 0x13 before, and in that, I could easily plot a pixel using:So, in vbe, how can i determine the color ?? is there any fixed pallete as in mode 0x13 ??Code: Select all
VGA[offset] = color
Read the spec.
Re: vbe functions in protected mode
Hi,
For better video modes it's a system of masks and shifts - something vaguely like:
However, for performance you'd want to have special case routines for common cases. For example, you might have a function pointer, and (for 16-bpp video modes where the masks and shifts match) your function pointer might point to code that does this:
Of course it's entirely possible to get fancy. E.g. you might just draw everything in 96-bpp in your buffer in RAM, and convert that to whatever the video card happens to want when blitting to the video card. In this case plotting a pixel might always be:
..and you'd have a function pointer that points to one of several different "convert while blitting" functions.
Cheers,
Brendan
For 8-bpp video modes the colours are mostly the same (colour = whatever you programmed the DAC to be for that index).snasim2002 wrote:I have programmed in mode 0x13 before, and in that, I could easily plot a pixel using:So, in vbe, how can i determine the color ?? is there any fixed pallete as in mode 0x13 ??Code: Select all
VGA[offset] = color
For better video modes it's a system of masks and shifts - something vaguely like:
Code: Select all
video_display_mapping[Y * bytes_per_line + X * bytes_per_pixel] = ((red >> (32-red_shift) ) & red_mask) | ((green >> (32-green_shift)) & green_mask) || ((blue >> (32-blue_shift)) & blue_mask)
Code: Select all
video_display_mapping[Y * bytes_per_line + X << 1] = (red >> 16) & 0xF800) | (green >> 21) & 0x07E0) || (blue >> 27)
Code: Select all
buffer[(Y * horizontal_resolution + X) * 12] = (red << 64) | (green << 32) | blue
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
-
- Member
- Posts: 37
- Joined: Sat Apr 11, 2015 9:37 am
Re: vbe functions in protected mode
Did it. At last, it works.
Thanx to Brendan, alexfru, and Combuster.
Code: Select all
void putpixel_mode_103(uint16_t x,uint16_t y,uint8_t color)
{
uint32_t addr = (y * MIB->pitch) + x;
uint8_t* screenptr = MIB->physbase;
screenptr[addr] = color;
}