Page 1 of 1
Frame Buffer Mapping - Another thread
Posted: Sun Dec 21, 2008 12:49 pm
by piranha
I am currently using patched grub to setup 800x600 video mode for me. I am trying to color the screen white. I know the code that actually does it works, as when I run it before paging, the screen becomes white.
I am using JamesM's tutorials for my memory management.
The code that I'm using to map is as follows:
Code: Select all
int a;
char *vga;
a = (int)0xE0000000;
vga=a;
for (i = v->phys_base_ptr; i < (v->phys_base_ptr + (xr*yr*(bpp/8))); i += 0x1000,a += 0x1000)
{
page_t *p = get_page (a, 1, current_directory);
p->frame = i;
p->rw = 1;
p->user = 0;
p->present = 1;
}
When I run the screen coloring code after paging is enabled, and after I run the above code, I only get about 1.75 lines colored at the top of the screen.
I've searched around already, but I still can't figure it out. Any ideas?
-JL
Re: Frame Buffer Mapping - Another thread
Posted: Sun Dec 21, 2008 2:21 pm
by kmtdk
well
my first guess is:
the mapping are to far away.
Meaning that when you are writing the screen, the address you are pointing at, is behind the "real" address.
example:
you have mapped, so that 0x1000 is 0x0000
and you are supossed to wrtie to the "REAL" address 0x2000
then writing at 0x2000 = 0x3000
so the currect address is 0x1000
IF you are sure about this, then more details are needed to find the problem
KMT dk
Re: Frame Buffer Mapping - Another thread
Posted: Sun Dec 21, 2008 2:25 pm
by piranha
Alright, I think I know what you mean, but can you put that in terms of my addresses if possible?
thanks, JL
Re: Frame Buffer Mapping - Another thread
Posted: Sun Dec 21, 2008 6:42 pm
by Brendan
Hi,
piranha wrote:Code: Select all
for (i = v->phys_base_ptr; i < (v->phys_base_ptr + (xr*yr*(bpp/8))); i += 0x1000,a += 0x1000)
This looks dodgy to me - often there's unused bytes on the right hand side of video display memory for padding. For example, for 800 * 600 * 32 bpp each line can be 4096 bytes where the first 3200 bytes are visible pixels and the remaining 896 bytes are padding, so video memory looks like this:
Code: Select all
************......
************......
************......
************......
************......
There should be a "bytes_per_line" field somewhere, and you should map "y_resolution * bytes_per_line" bytes (as a minimum).
piranha wrote:When I run the screen coloring code after paging is enabled, and after I run the above code, I only get about 1.75 lines colored at the top of the screen.
You didn't say, but I'd assume this works out to 24 bpp mode and only the first page is mapped correctly (4096 / 3 / 800 = 1.706666 lines). It should be easy to find the problem with Bochs debugger, but I'd guess the "xr", "yr" or "bpp" variables don't contain what they should and the loop exits early.
Cheers,
Brendan
Re: Frame Buffer Mapping - Another thread
Posted: Mon Dec 22, 2008 12:18 pm
by piranha
Yeah, I just had it print the values, and yes, xr and yr are negative numbers, along with bpp.
I'll work on it...
Edit: I defined the variables as unsigned, and now the values are xr=61440, yr=65363, and bpp=255
Edit2:
Code: Select all
kprintf("Mapping...\n");
for (i = v->phys_base_ptr; i < (v->phys_base_ptr + (yr*v->bytes_per_scan_line)); i += 0x1000,a += 0x1000)
{
kprintf("1 page\n");
only prints "Mapping...", but not "1 page", so v->phys_base_ptr + (yr*v->bytes_per_scan_line) must be less than v->phys_base_ptr...
-JL
Re: Frame Buffer Mapping - Another thread
Posted: Mon Dec 22, 2008 9:37 pm
by Brendan
Hi,
piranha wrote:Edit: I defined the variables as unsigned, and now the values are xr=61440, yr=65363, and bpp=255
It's very unlikely those are sane values for any video mode...
piranha wrote:only prints "Mapping...", but not "1 page", so v->phys_base_ptr + (yr*v->bytes_per_scan_line) must be less than v->phys_base_ptr...
Are you sure "bytes_per_scan_line" is sane? Given that none of the other variables are sane, I'd assume "bytes_per_scan_line" is also wrong.
Also note that for C, multiplying 2 large numbers together can easily give you the wrong answer due to undetected overflow. If "v->phys_base_ptr + (yr*v->bytes_per_scan_line)" is less than or equal to "v->phys_base_ptr"; then "(yr*v->bytes_per_scan_line)" must be less than or equal to zero, which definitely isn't right. Further, if "yr=65363" then "bytes_per_scan_line" must be either negative, zero, or larger than "INT_MAX / 65363".
I'm guessing you've got code somewhere that gets details for the selected video mode from a VESA/VBE "mode info" structure. I'd assume this code is entirely borked, and that there's possibly nothing wrong with the code to map video display memory into the virtual address space...
Cheers,
Brendan
Re: Frame Buffer Mapping - Another thread
Posted: Mon Dec 22, 2008 11:43 pm
by piranha
Hmm...yeah, thats the conclusion I came up with.
I have
struct vbemodeinfo *v;
v = (struct vbemodeinfo *)mboot_ptr->vbe_mode_info;
mboot_ptr is the multiboot pointer struct, which I'm assuming is OK, because other values from it seem to be correct.
Here is the structure...vbemodeinfo. After writing one myself, I borrowed this one from a linux driver. So it should work, right?
Code: Select all
u16 mode_attr;
u8 winA_attr;
u8 winB_attr;
u16 win_granularity;
u16 win_size;
u16 winA_seg;
u16 winB_seg;
u32 win_func_ptr;
u16 bytes_per_scan_line;
u16 x_res;
u16 y_res;
u8 x_char_size;
u8 y_char_size;
u8 planes;
u8 bits_per_pixel;
u8 banks;
u8 memory_model;
u8 bank_size;
u8 image_pages;
u8 reserved1;
u8 red_len;
u8 red_off;
u8 green_len;
u8 green_off;
u8 blue_len;
u8 blue_off;
u8 rsvd_len;
u8 rsvd_off;
u8 direct_color_info;
unsigned int phys_base_ptr;
u8 reserved2[6];
Edit: Is there a specific place that the framebuffer is physically mapped to in Qemu?
-JL