OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Apr 19, 2024 8:50 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: How do you achieve VGA graphics WITHOUT RealMode/BIOS calls?
PostPosted: Thu Apr 26, 2018 11:49 pm 
Offline
Member
Member

Joined: Thu Apr 26, 2018 11:21 pm
Posts: 49
My OS is at the stage where it can dynamically load and link drivers from PE format data into the kernel.

So it's time for a graphics driver to keep me motivated, because I want a "proper" OS. I know I could set the graphics during the Real Mode stages but I really don't like that solution.

Obviously if some 16-bit BIOS routine can properly initialise the video device, what's really stopping me from doing the same with IO ports in protected mode?

Really I only plan to run my OS in virtual machines (QEMU/Bochs/VirtualBox) and they all seem to simulate the same graphics device, similar to Cirrus Logic devices (please correct me if I'm wrong).

So I'd be more than happy to write the best Cirrus driver I can, and share the code here if I can get some pointers on what I need to do to:

1. Properly switch modes from the default 80x25 textmode to at least 320x200 256 colours using IO ports only
2. Plot specific pixels on the screen

Here's my current code which gets QEMU to a pure black screen, Bochs to an almost solid grey but with some corrupt pixels at the bottom and VirtualBox to a black background with grey lines and rectangles all over the place (seems like a textmode hang over).

Note: I memset locations 0xA000 and 0xA0000 to 0xFF after this is executed, also I have little idea what I'm doing I just tried different registers to achieve a different result than my first attempt (random pixels/rectangles/lines everywhere).


Code:
   WRITEREG VGA_MISC_WRITE, 0x03
   
   ; Plane mask
   WRITEREG VGA_SEQ_INDEX, 2
   WRITEREG VGA_SEQ_DATA, 0   
   
   ; Extended memory
   WRITEREG VGA_SEQ_INDEX, 4
   WRITEREG VGA_SEQ_DATA, 2
   ;
   ; CRTC crap, horizontal total and end, vertical total
   WRITEREG VGA_CRTC_INDEX, 0
   WRITEREG VGA_CRTC_DATA, 0
   WRITEREG VGA_CRTC_INDEX, 1
   WRITEREG VGA_CRTC_DATA, 1
   WRITEREG VGA_CRTC_INDEX, 6
   WRITEREG VGA_CRTC_DATA, 0

   ; Screen start address
   WRITEREG VGA_CRTC_INDEX, 0xC
   WRITEREG VGA_CRTC_DATA, 0xA0
   WRITEREG VGA_CRTC_INDEX, 0xD
   WRITEREG VGA_CRTC_DATA, 0x00
   
   WRITEREG VGA_GC_INDEX, 6
   WRITEREG VGA_GC_DATA, 00000001b
   


Top
 Profile  
 
 Post subject: Re: How do you achieve VGA graphics WITHOUT RealMode/BIOS ca
PostPosted: Fri Apr 27, 2018 2:29 am 
Offline
Member
Member

Joined: Tue May 13, 2014 3:02 am
Posts: 280
Location: Private, UK
What you want to do is entirely possible and widely compatible (the only time you may have problems is on a system booted from UEFI that leaves the display in a high-resolution mode; not a problem if you're only targetting VMs).

Its seems you're on the right track with the code you have so fare... The Wiki contains complete-ish listings of the register settings for various modes, the FreeVGA site contains detailed reference material (you'll want the pages under "VGA Chipset Reference").

If you're interested in higher output resolutions, most VMs implement a virtual graphics adaptor based on the "Bochs Graphics Adaptor" or "BGA". There's some documentation on the Wiki for that, under a somewhat misleading title (it has little to do with VBE)...

_________________
Image


Top
 Profile  
 
 Post subject: Re: How do you achieve VGA graphics WITHOUT RealMode/BIOS ca
PostPosted: Fri Apr 27, 2018 3:00 am 
Offline
Member
Member

Joined: Thu Apr 26, 2018 11:21 pm
Posts: 49
The Bochs Graphics Adaptor you mentioned looks very suitable to what I need right now, as the Wiki says it's supported in QEMU, Bochs and VirtualBox, so that's really cool. Then maybe later on when most of the OS is done (been at it probably 6 months collectively) I could add basic support for an actual video card like Intel/AMD and have it on real hardware.

I'm probably going to spend the weekend experimenting with BGA, shaping the type of driver design I want etc. I'll definitely let you know how I get on and I'll post the code here if it works out.

Thanks! 8)


Top
 Profile  
 
 Post subject: Re: How do you achieve VGA graphics WITHOUT RealMode/BIOS ca
PostPosted: Fri Apr 27, 2018 8:30 pm 
Offline
Member
Member

Joined: Thu Apr 26, 2018 11:21 pm
Posts: 49
Did it!

Here is my BGA configuration and mode setting code, you call VGAInit to configure which returns a bool 0 or 1 in EAX for success or fail, so you have an opportunity to do something about the result, then when you actually want to change the resolution you call VGAEnable.

This works perfectly in QEMU, VirtualBox and Bochs. On the plus side, this enables an arbitrary (720x480) resolution AND 24 bits-per-pixel so you can have proper, full colour HD graphics in your OS, on the downside it is probably constrained to those environments so if you want to take your hard work to real hardware, you're going to have to look at the specs and datasheets needed and write a whole new graphics driver for that hardware (it has been done).

QEMU notes: I love QEMU, it's the fastest for development in my opinion. But it's configured to use PCI Bochs Graphics VBE, and I couldn't get the ISA configuration which Bochs and VirtualBox use. QEMU crashed or didn't open depending on what I did.

Emulators with an ISA setup use the hardcoded address 0xE0000000 for VRAM.

Emulators with a PCI setup need you to read the VRAM address from BAR0 of PCI device 0x1234:0x1111 (vendor:device slot respectively)

So for QEMU and any other possible emulators/configurations that demand the PCI setup, I also needed a tiny bit of PCI enumeration code to read the VRAM address off BAR0 which isn't that complex. That code (which I will leave as an exercise to the reader) is based off the Wiki's PCI page with slight adjustments and a function to read 32-bit values from the PCI configuration space. In QEMU, my setup returns 0xFD000008 as the VRAM address but this causes a few pixels to be missed at the top... EDIT: As noted in the post below, the last 4 bits aren't meant to be used so the '8' isn't part of the address. The address is also 16-byte aligned. You can discard those bits to get something like 0xFD000000 etc

I tested this with memset code to draw a grey screen with a black line in the middle which works in all emulators, that code is at the bottom.

Thanks for letting me know about BGA!

LJ

Code:
   %macro READREG16 1
   mov dx, %1
   in ax, dx
%endmacro

%macro WRITEREG16 2
   mov dx, %1
   mov ax, %2
   out dx, ax
%endmacro

VBE_DISPI_IOPORT_INDEX         EQU 0x01CE
VBE_DISPI_IOPORT_DATA         EQU 0x01CF

VBE_DISPI_INDEX_ID               EQU 0x0
VBE_DISPI_INDEX_XRES             EQU 0x1
VBE_DISPI_INDEX_YRES             EQU 0x2
VBE_DISPI_INDEX_BPP              EQU 0x3
VBE_DISPI_INDEX_ENABLE           EQU 0x4
VBE_DISPI_INDEX_BANK             EQU 0x5
VBE_DISPI_INDEX_VIRT_WIDTH       EQU 0x6
VBE_DISPI_INDEX_VIRT_HEIGHT      EQU 0x7
VBE_DISPI_INDEX_X_OFFSET         EQU 0x8
VBE_DISPI_INDEX_Y_OFFSET         EQU 0x9

VBE_DISPI_ID0               EQU 0xB0C0
VBE_DISPI_ID1               EQU 0xB0C1
VBE_DISPI_ID2               EQU 0xB0C2
VBE_DISPI_ID3               EQU 0xB0C3
VBE_DISPI_ID4               EQU 0xB0C4

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

VBE_DISPI_LFB_PHYSICAL_ADDRESS   EQU 0xE0000000

VGASetMode:
   ; Returns 1 or 0 (true/false) if successful or not.
   push edx

.setVersion:
   ; Try set 0xB0C4 for 8MB VRAM.
   WRITEREG16 VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID
   WRITEREG16 VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID4
   
   WRITEREG16 VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID
   READREG16 VBE_DISPI_IOPORT_DATA
   
   cmp ax, VBE_DISPI_ID4
   jne .error
   
.configure:
   ; Try set 24 bits per pixel
   WRITEREG16 VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP
   WRITEREG16 VBE_DISPI_IOPORT_DATA, 24
   
   WRITEREG16 VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP
   READREG16 VBE_DISPI_IOPORT_DATA
   
   ; Set resolution
   WRITEREG16 VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES
   WRITEREG16 VBE_DISPI_IOPORT_DATA, 720
   
   WRITEREG16 VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES
   WRITEREG16 VBE_DISPI_IOPORT_DATA, 480
   
.ok:
   mov eax, 1
   jmp .done
   
.error:
   mov eax, 0
   
.done:
   pop edx
   
   ret
   
VGAEnable:
   WRITEREG16 VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE
   WRITEREG16 VBE_DISPI_IOPORT_DATA, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED
   
   ret

Fill the screen with 24bpp grey and draw a line at x=10, y=10:
Code:
VRAM = VGAFindVRAMAddress(); // PCI enumeration code for QEMU but returns hardcoded address 0xE0000000 when device 0x1234:0x1111 isn't found.
VGAEnable();
memset(VRAM, 0xAF, (720 * 480) * 3); // Fill with grey
memset(VRAM + (10 * 3) + ((3 * 720) * 10), 0x00, 100 * 3); // Draw line


Attachments:
File comment: Running in all emulators!
Untitled.jpg
Untitled.jpg [ 107.48 KiB | Viewed 2374 times ]


Last edited by rwosdev on Sat Apr 28, 2018 1:42 am, edited 2 times in total.
Top
 Profile  
 
 Post subject: Re: How do you achieve VGA graphics WITHOUT RealMode/BIOS ca
PostPosted: Sat Apr 28, 2018 12:30 am 
Online
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5137
rwosdev wrote:
In QEMU, my setup returns 0xFD000008 as the VRAM address but this causes a few pixels to be missed at the top, but I've observed no ill effects from aligning it to 0x1000 so it is 0xFD000000.

The lowest four bits of that BAR indicate that it's a prefetchable 32-bit memory space BAR, they're not part of the address. You can read more about that in the wiki.


Top
 Profile  
 
 Post subject: Re: How do you achieve VGA graphics WITHOUT RealMode/BIOS ca
PostPosted: Sat Apr 28, 2018 1:35 am 
Offline
Member
Member

Joined: Thu Apr 26, 2018 11:21 pm
Posts: 49
Overlooked that, thanks!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 168 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group