VBE Troubles (LFB Mode not used by QEMU)

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

VBE Troubles (LFB Mode not used by QEMU)

Post by zhiayang »

As the title says, QEMU refuses to set the display mode to LFB.
QEMU is the latest from HomeBrew.

Here's what I'm using (straight from the wiki)

Code: Select all

void HAL_BgaSetVideoMode(unsigned int Width, unsigned int Height, unsigned int BitDepth, uint8_t UseLinearFrameBuffer, uint8_t ClearVideoMemory, uint8_t GetCaps)
{
	HAL_BgaWriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);
	HAL_BgaWriteRegister(VBE_DISPI_INDEX_XRES, Width);
	HAL_BgaWriteRegister(VBE_DISPI_INDEX_YRES, Height);
	HAL_BgaWriteRegister(VBE_DISPI_INDEX_BPP, BitDepth);
	HAL_BgaWriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED |
		(UseLinearFrameBuffer ? VBE_DISPI_LFB_ENABLED : 0) |
		(ClearVideoMemory ? 0 : VBE_DISPI_NOCLEARMEM) |
		(GetCaps ? VBE_DISPI_GETCAPS : 0));
}
In QEMU, writing to 0xE000 0000 does nothing. I need to use banked mode and write to 0xA0000 to get anything to appear on screen at all.

In Bochs, everything works as expected and I can write to the whole screen at 0xE000 0000.

What's wrong with QEMU? I'm using (-vga std) with it...


PS: In case you're wondering... I would use Bochs as my go-to emulator, but I'm using ST2 as my 'IDE' and Bochs doesn't open it's XQuartz window when launched from there.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: VBE Troubles (LFB Mode not used by QEMU)

Post by bluemoon »

Did you hard-code E0000000 or it is the BAR you got from PCI?

In my testbed, qemu (both mac and linux mint 14) return the following:

Code: Select all

    PCI : bus:0 slot:0 func:0  device:00001237 vendor:00008086 class:6:0
    PCI : bus:0 slot:1 func:0  device:00007000 vendor:00008086 class:6:1
    PCI : bus:0 slot:1 func:1  device:00007010 vendor:00008086 class:1:1
    PCI : bus:0 slot:2 func:0  device:00001111 vendor:00001234 class:3:0
    BGA : Detected device @ pci  | bus:0 slot:2 func:0
    PCI : bus:0 slot:3 func:0  device:00008139 vendor:000010EC class:2:0
   8139 : Detected device @ pci  | bus:0 slot:3 func:0 | IO: 49152 IRQ:11
The BGA's BAR is FD000000, with size 00C00000

This is my start script:

Code: Select all

#!/bin/sh
echo Launching QEmu, Press Ctrl-A x to terminate VM.

QEMU="qemu-system-x86_64"
IMAGE="bluemoon.img"
NIC="-netdev type=user,id=net -device rtl8139,netdev=net"

if [ "$1" = "debug" ]
then
  echo [!] DEBUG MODE ON, use gdb to start debug this VM.
  $QEMU -m 32 -S -s $IMAGE
elif [ "$1" = "bga" ]
then
  $QEMU -m 32 -vga std -serial stdio $NIC $IMAGE
elif [ "$1" = "vga" ]
then
  $QEMU -m 32 -vga cirrus -serial stdio $NIC $IMAGE
else
  $QEMU -m 32 -nographic $NIC $IMAGE
fi
User avatar
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

Re: VBE Troubles (LFB Mode not used by QEMU)

Post by zhiayang »

First of all, I am completely aware that this is a post from over 5 months ago. I was also the OP, and completely forget about this topic.

I've been laying of OSDev for some time now due to studies and stuff like that. But I've recently freed up some time and I'm looking forward to getting back to OSDev again.

Now this problem.

I'm able to read the DeviceID and VendorID of the PCI device (as bluemoon suggested) and it's also in Bus0 Slot2.
This is the problem: Using PCI, I've gotten that I need to read the PCI config offset by 0x10 to get the LFB address stored in BAR0.


First of all, I do a nested-for-loop to scan all buses and slots for devices. Then, if it existed, I write 0xFFFFFFFF to the BAR0 address to reset the BAR (I read that somewhere).

However, reading BAR0 with LFBAddr = HAL_PCIReadConfig32(MakePCIAddr(0, 2, 0), 0x10); yields 0x08 for the Bochs VBE device and 0x00 for the other devices. Is there anything I'm doing wrong?

Code: Select all

uint32_t MakePCIAddr(uint16_t Bus, uint16_t Slot, uint16_t Function)
{
	return (uint32_t)((Bus << 16) | (Slot << 11) | (Function << 8) | 1 << 31);
}

uint32_t HAL_PCIReadConfig32(uint32_t Address, uint16_t Offset)
{
	// Write the address to read.
	outl(0xCF8, Address + Offset);

	// Read the **** inside.
	// return ((uint16_t)((inl(0xCFC) >> ((Offset & 0x2) * 8)) & 0xFFFF));
	return (uint16_t)(inl(0xCFC));
}

void HAL_PCIWriteConfig32(uint32_t Address, uint16_t Offset, uint32_t Data)
{
	// Write the address to read.
	outl(0xCF8, Address + Offset);

	// Read the **** inside.
	// return ((uint16_t)((inl(0xCFC) >> ((Offset & 0x2) * 8)) & 0xFFFF));
	outl(0xCFC, Data);
}


void HAL_PCIInitBAR(uint16_t Bus, uint16_t Slot, uint16_t Function)
{
	HAL_PCIWriteConfig32(MakePCIAddr(Bus, Slot, Function), 0x10, 0xFFFFFFFF);
}


uint16_t HAL_PCICheckDeviceExistence(uint16_t Bus, uint16_t Slot)
{
	if(HAL_PCIReadConfig32(MakePCIAddr(Bus, Slot, 0), 0) == 0xFFFF)
	{
		// Non-existent devices return 0xFFFF on read.
		return 0;
	}
	else
		return 1;
}
User avatar
Combuster
Member
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 Troubles (LFB Mode not used by QEMU)

Post by Combuster »

Type error: 16-bit value in function return where 32 bits are expected.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

Re: VBE Troubles (LFB Mode not used by QEMU)

Post by zhiayang »

Combuster wrote:Type error: 16-bit value in function return where 32 bits are expected.
Oh. My. Gosh.

I guess I need to re-evaluate my debugging skills, I did not expect to have overlooked such a trivial yet common error.
User avatar
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

Re: VBE Troubles (LFB Mode not used by QEMU)

Post by zhiayang »

Whoops, I'm back again.

This time I've gotten the BGA and everything to work in QEMU... but only in QEMU. In VBox and Parallels (I know parallels has no BGA, I was testing this PCI stuff), I get DeviceID = VendorID... and only there.

Using this to read the device and vendor ID:

Code: Select all

vendor = HAL_PCIReadConfig16(MakePCIAddr(bus, slot, 0), 0);
device = HAL_PCIReadConfig16(MakePCIAddr(bus, slot, 0), 2);

Code: Select all

uint32_t MakePCIAddr(uint16_t Bus, uint16_t Slot, uint16_t Function)
{
	return (uint32_t)((Bus << 16) | (Slot << 11) | (Function << 8) | 1 << 31);
}


uint16_t HAL_PCIReadConfig16(uint32_t Address, uint16_t Offset)
{
	// Write the address to read.
	outl(0xCF8, Address + Offset);

	// Read the **** inside.
	// return ((uint16_t)((inl(0xCFC) >> ((Offset & 0x2) * 8)) & 0xFFFF));
	return (inw(0xCFC));
}
I'm reading in a word as I should (inw), and the offsets should then be correct... What am I doing wrong?

Thanks!
User avatar
Combuster
Member
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 Troubles (LFB Mode not used by QEMU)

Post by Combuster »

That's because QEMU is stupid and doesn't properly implement PCI - just enough so that good code will just happen to work.
I'm reading in a word as I should
Wrong. Always read and write doublewords. Always read and write on doubleword boundaries. Real PCI ignores the bottom two bits of the offset.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

Re: VBE Troubles (LFB Mode not used by QEMU)

Post by zhiayang »

Combuster wrote:That's because QEMU is stupid and doesn't properly implement PCI - just enough so that good code will just happen to work.
I'm reading in a word as I should
Wrong. Always read and write doublewords. Always read and write on doubleword boundaries. Real PCI ignores the bottom two bits of the offset.
Right. That would be useful information to add to the wiki, nothing I read told me about reading from dwords...

In the spirit of making this useful to google-goers, all you need to do to fix it is to shift the received dword 16 bits right (for device)
User avatar
Combuster
Member
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 Troubles (LFB Mode not used by QEMU)

Post by Combuster »

requimrar wrote:That would be useful information to add to the wiki, nothing I read told me about reading from dwords.
Why should I?
wiki wrote:Two 32-bit I/O locations
(...)
7-2: register
1-0: 00
And no, I didn't just edit that in :wink:

P.S. Did you have a good look at that one line of code you commented out for some reason this whole thread?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Mikemk
Member
Member
Posts: 409
Joined: Sat Oct 22, 2011 12:27 pm

Re: VBE Troubles (LFB Mode not used by QEMU)

Post by Mikemk »

Combuster wrote:P.S. Did you have a good look at that one line of code you commented out for some reason this whole thread?
lol. That's funny.
Programming is 80% Math, 20% Grammar, and 10% Creativity <--- Do not make fun of my joke!
If you're new, check this out.
User avatar
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

Re: VBE Troubles (LFB Mode not used by QEMU)

Post by zhiayang »

One last issue: (I realise this is somewhat of a necropost -- is there an exception to doing it on your own topic? (: )

Anyway, I'm using

Code: Select all

printk("%x", (HAL_PCIReadConfig32(MakePCIAddr(bus, slot, 0), 0x10)));
To read the LFB address (I know I don't save it anywhere, it's handled elsewhere).

However, I'm getting 0xFD000008, and have been since the beginning; I'd thought it's some weird quirk but no, it's actually supposed to be 0xFD000000 because it seems the first two pixels are not accessible from the 0xFD000008 address (duh, now that I know).

Is there some issue with me reading the PCI BAR? It probably is...

Thanks!



EDIT: Kind Sir 'froggey' on #osdev pointed me to the PCI page that states the bottom 2/4 bits of the BAR are used for other things...
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: VBE Troubles (LFB Mode not used by QEMU)

Post by bluemoon »

Check the wiki PCI
The lower 4 bits are attributes.
Post Reply