Page 1 of 1
vbe functions in protected mode
Posted: Fri Jan 22, 2016 9:53 am
by snasim2002
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
Re: vbe functions in protected mode
Posted: Fri Jan 22, 2016 10:14 am
by Combuster
segment registers [...] can only address 64 kb of memory
Not quite true.
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
Posted: Fri Jan 22, 2016 8:40 pm
by Brendan
Hi,
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 ??
There's 3 different cases:
- 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 both of the protected mode interfaces, I think you'd create a GDT entry to use for ES and VBE should be happy with that. However; I'd strongly recommend avoiding VBE's protected mode interfaces - they're annoying and there's no guarantee the video card supports them (e.g. even if you know the video card is VBE 3.0 you still can't assume it implemented the optional 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 last 2 cases you're able to do anything you like (e.g. map the page where your structure is into the virtual8086 code's 1 MiB address space); but it's a lot of work that (in my opinion) mostly adds up to a waste of time and I don't think it's worth the hassle.
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.
snasim2002 wrote:i am NOT using a v8086 handler, but i can safely jump to real mode and execute interrupts there.
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).
Cheers,
Brendan
Re: vbe functions in protected mode
Posted: Sun Jan 24, 2016 11:15 pm
by snasim2002
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 ?
Re: vbe functions in protected mode
Posted: Sun Jan 24, 2016 11:53 pm
by Brendan
Hi,
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 ?
There's 2 different ways to access display memory.
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
Re: vbe functions in protected mode
Posted: Mon Jan 25, 2016 12:04 am
by alexfru
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.
Re: vbe functions in protected mode
Posted: Mon Jan 25, 2016 12:11 am
by snasim2002
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 ??
Re: vbe functions in protected mode
Posted: Mon Jan 25, 2016 12:34 am
by alexfru
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 ??
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.
Read the spec.
Re: vbe functions in protected mode
Posted: Mon Jan 25, 2016 12:35 am
by Brendan
Hi,
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 ??
For 8-bpp video modes the colours are mostly the same (colour = whatever you programmed the DAC to be for that index).
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)
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:
Code: Select all
video_display_mapping[Y * bytes_per_line + X << 1] = (red >> 16) & 0xF800) | (green >> 21) & 0x07E0) || (blue >> 27)
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:
Code: Select all
buffer[(Y * horizontal_resolution + X) * 12] = (red << 64) | (green << 32) | blue
..and you'd have a function pointer that points to one of several different "convert while blitting" functions.
Cheers,
Brendan
Re: vbe functions in protected mode
Posted: Mon Jan 25, 2016 1:12 am
by snasim2002
Did it. At last, it works.
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;
}
Thanx to Brendan, alexfru, and Combuster.