Page 1 of 3

SVGA in 32bit protected mode ?

Posted: Mon Dec 04, 2006 5:43 pm
by MagicalTux
Well..
I started with some friends to write an OS «just for fun» (and maybe a little more) and we're wondering what is the best way to handle GFX mode.
Yeah, we're aiming to do a mainly graphical OS, however we want to do it the hard way.

I did some research and found that VESA VBE 2.0 should be called in 16bit mode (or v86), however it's too easy.

Since we all use QEmu for the tests, and since QEmu is used by some people here, I was wondering if someone had tips or code snips about how to enumerate then switch to a gfx mode from 32bit protected mode (seems to simulate a Cirrus Logic GD5446 PCI VGA, from what the manpage says).

Well, btw tips and tricks are welcome. We started last week, and after some difficulties we managed to have a running bootloader, and be able to load and run some C code. I even wrote a minimalistic printf-like function which uses teletype bios interrupt to write text to the screen.

Re: SVGA in 32bit protected mode ?

Posted: Mon Dec 04, 2006 6:02 pm
by Walling
MagicalTux wrote:Well..
I did some research and found that VESA VBE 2.0 should be called in 16bit mode (or v86), however it's too easy.
I don't know Qemu well, but I have played a with some VESA graphics. A solution could be to find and setup the VESA mode, switch to it and query the physical address for the video memory in 16 bit real mode. Then you can switch to protected mode and just write to that memory address (calculated for the pixel). It should show up immediately. It worked for me in Bochs emulator.

But if you read the VESA VBE 2.0 specification it should tell you about protected mode access. The BIOS has to support it though. As far as I know Bochs doesn't do this (a pity), but maybe Qemu does.

Other solutions might exists. I have thought of an pmode-rmode-bridge. But that, I think, may be out of scope of your project.

Posted: Mon Dec 04, 2006 6:25 pm
by MagicalTux
The QEmu bios is bochs'... and the implementations are almost the same. However QEmu have an option documented in the man page :

-std-vga
Simulate a standard VGA card with Bochs VBE extensions (default is Cirrus Logic GD5446 PCI VGA). If your guest OS supports the VESA 2.0 VBE extensions (e.g. Windows XP) and if you want to use high resolution modes (>= 1280x1024x16) then you should use this option.

Dunno if this can be used... Well anyway I'll try to do the gfx init from 16bit mode, but I'm not sure I'll be able to do things like addressing 800x600 resolution in 32bit mode (yeah, I don't have much experience with that).

Posted: Mon Dec 04, 2006 6:58 pm
by Walling
MagicalTux wrote:Dunno if this can be used... Well anyway I'll try to do the gfx init from 16bit mode, but I'm not sure I'll be able to do things like addressing 800x600 resolution in 32bit mode (yeah, I don't have much experience with that).
Try it.

Most possible you get an video address like 0xE0000000 (ie. 3,5 GiB address point), I did. Save it. If you have choosen 32 bit color depth and 800x600 resolution, the thing goes like this in C:

Code: Select all

uint32 * screenBase = 0xE0000000; // or whatever value you get
uint32 screenWidth = 800;
uint32 screenHeight = 600;

void drawPixel(uint32 x, uint32 y, uint32 rgbColor) {
  uint32 * address = screenBase + screenWidth * y + x;
  *address = rgbColor;
}

// Define some colors (as you know them in HTML):
const uint32 Black = 0x000000;
const uint32 Red = 0xFF0000;
const uint32 Green = 0x00FF00;
const uint32 Blue = 0x0000FF;
const uint32 Gray = 0x999999;
const uint32 White = 0xFFFFFF;
A good thing is to print debugging info about the VESA mode you select and everything else before you switch to graphics mode. Wait for a key press or halt the execution using some debugging features in Qemu (if it exists). In graphics mode you can't print text as in the regular text mode. You would have to draw it yourself.

If you know how, then have some fun by drawing the Mandelbrot fractal or similar. It's feels good when it boots up and displays a complex and beautiful picture like that :-)

Posted: Mon Dec 04, 2006 7:25 pm
by TheQuux
I just implemented that, so I released a new version of Xenon just now, for Qemu users only. It's avaliable from the link below.

Essentially, you get a big, 1024x768 fat text console.

Enjoy!

Also, look at the qemu source, in hw/cirrus_vga.c, and the linux source, in drivers/video/cirrusfb.c; that is much better code than this.

EDIT: for this one, you need the Cirrus SVGA adapter, so no -std-vga

Posted: Mon Dec 04, 2006 8:40 pm
by Dex
Here's a demo i wrote sometime ago, that switch between veas and text mode every 10 seconds in pmode, may help ?.
http://www.dex4u.com/demos/DemoVesa.zip

Note: i was called ASHLEY4 then .

Posted: Tue Dec 05, 2006 1:11 am
by xdopamine
Hi,
here is some code i have written sometime ago. It should work with Bochs as well as with Qemu (don't forget -std-vga):

Code: Select all


#define VBE_DISPI_IOPORT_INDEX 0x01CE
#define VBE_DISPI_IOPORT_DATA  0x01CF
#define VBE_DISPI_INDEX_ID              0x0
#define VBE_DISPI_INDEX_XRES            0x1
#define VBE_DISPI_INDEX_YRES            0x2
#define VBE_DISPI_INDEX_BPP             0x3
#define VBE_DISPI_INDEX_ENABLE          0x4
#define VBE_DISPI_INDEX_BANK            0x5
#define VBE_DISPI_INDEX_VIRT_WIDTH      0x6
#define VBE_DISPI_INDEX_VIRT_HEIGHT     0x7
#define VBE_DISPI_INDEX_X_OFFSET        0x8
#define VBE_DISPI_INDEX_Y_OFFSET        0x9

#define VBE_DISPI_DISABLED              0x00
#define VBE_DISPI_ENABLED               0x01
#define VBE_DISPI_GETCAPS               0x02
#define VBE_DISPI_8BIT_DAC              0x20
#define VBE_DISPI_LFB_ENABLED           0x40
#define VBE_DISPI_NOCLEARMEM            0x80

void vbe_write(USHORT index, USHORT value)
{
	WRITE_PORT_USHORT(VBE_DISPI_IOPORT_INDEX, index);
	WRITE_PORT_USHORT(VBE_DISPI_IOPORT_DATA, value);
}


void vbe_set(USHORT xres, USHORT yres, USHORT bpp)
{
	vbe_write(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);
	vbe_write(VBE_DISPI_INDEX_XRES, xres);
	vbe_write(VBE_DISPI_INDEX_YRES, yres);
	vbe_write(VBE_DISPI_INDEX_BPP, bpp);
	vbe_write(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);	
}
You can access the LFB at 0xe0000000 after calling vbe_set().

I have also written some code for the VMWare video adapter.
I can post it as well, if you want it.

Posted: Tue Dec 05, 2006 4:56 am
by Walling
core wrote:Hi,
here is some code i have written sometime ago. It should work with Bochs as well as with Qemu (don't forget -std-vga):
Very interesting. Thanks. Have to test that code. Where can I find a list of other VESA port commands to send? I want to query the available modes and their info.

Posted: Tue Dec 05, 2006 6:52 am
by MagicalTux
Wow, it works in protected mode !

Thanks a lot!!

(btw I had to use outw instead of WRITE_PORT_USHORT)

EDIT: Ok it works great, and I could display some nice images to test the 32 bits :)

Btw the vmware code is welcome too.

(Now I have to work on 32bit disk driver to avoid switching to 16bit mode while loading images)

Posted: Wed Dec 06, 2006 8:48 am
by Jeko
core wrote:Hi,
here is some code i have written sometime ago. It should work with Bochs as well as with Qemu (don't forget -std-vga).
this code works also with real pc?

Posted: Wed Dec 06, 2006 10:02 am
by Walling
It would be nice though if vbabios used by Bochs and Qemu supported the VBE3 protected mode entry point. Just found this bug report/feature request (obviously written by an OS developer): http://savannah.nongnu.org/support/?105170 Nobody ever answered it :(

Posted: Wed Dec 06, 2006 10:54 am
by Combuster
It would be nice though if vbabios used by Bochs and Qemu supported the VBE3 protected mode entry point. Just found this bug report/feature request (obviously written by an OS developer): http://savannah.nongnu.org/support/?105170 Nobody ever answered it :(
"Severity: 1 - Wish". Thats asking for being forgotten.

Suggestion: If somebody has time to spare, he might contribute to the bios and do the PMode entry point. Everything's here

Compiling VGABIOS

Posted: Wed Dec 06, 2006 12:12 pm
by Walling
Combuster wrote:Suggestion: If somebody has time to spare, he might contribute to the bios and do the PMode entry point. Everything's here
I've downloaded the source, but it won't compile. I've installed the Bin86 package, which is needed. It just says:

Code: Select all

% make
gcc -E vgabios.c  -DVBE "-DVGABIOS_DATE="`date '+%d %b %Y'`"" > _vgabios_.c
bcc -o vgabios.s -C-c -D__i86__ -S -0 _vgabios_.c
_vgabios_.c:1: error: Unknown preprocessor directive
_vgabios_.c:2: error: Unknown preprocessor directive
_vgabios_.c:3: error: Unknown preprocessor directive
_vgabios_.c:4: error: Unknown preprocessor directive
...
...
Is 'bcc' broken or have I compiled it in a wrong way (the Bin86 package). Anyone?

I might contribute. It can't be that difficult to code an entrypoint. It is 16 bit protected mode, so it could just call the current implementation I think. Of course I would have to look into that and the VBE3 specification.

Posted: Wed Dec 06, 2006 12:24 pm
by AirFlight
You could download windows ddk and there you will find AGP display driver, so you could program graphics chip yourself.
BTW, there is VESA 3.0 by now. There is routine to ask VESA to give you address at start of frame buffer. example he returned to me ed000000h.
Go to vesa site and read specifications.
http://www.vesa.org/public/VBE
That will do it. :wink:

Posted: Wed Dec 06, 2006 12:41 pm
by Walling
AirFlight wrote:You could download windows ddk and there you will find AGP display driver, so you could program graphics chip yourself.
BTW, there is VESA 3.0 by now. There is routine to ask VESA to give you address at start of frame buffer. example he returned to me ed000000h.
Go to vesa site and read specifications.
http://www.vesa.org/public/VBE
That will do it. :wink:
The problem is that you can't do it only from protected mode right now. You can if the BIOS supports the protected mode entry point as explained in the VBE3 specification, but AFAIK the 'vgabios' used in Bochs and Qemu doesn't support it. My current solution is to jump into real mode every time I need to do a VESA command, but that is not very efficient.