Page 1 of 1

VBE Troubles (LFB Mode not used by QEMU)

Posted: Fri Nov 30, 2012 10:30 am
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.

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

Posted: Fri Nov 30, 2012 10:49 am
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

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

Posted: Fri May 10, 2013 5:42 am
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;
}

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

Posted: Fri May 10, 2013 6:08 am
by Combuster
Type error: 16-bit value in function return where 32 bits are expected.

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

Posted: Fri May 10, 2013 8:59 am
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.

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

Posted: Sat May 11, 2013 12:37 am
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!

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

Posted: Sat May 11, 2013 1:47 am
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.

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

Posted: Sat May 11, 2013 8:46 am
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)

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

Posted: Sat May 11, 2013 11:11 am
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?

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

Posted: Sat May 11, 2013 12:35 pm
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.

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

Posted: Sun May 19, 2013 5:24 am
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...

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

Posted: Sun May 19, 2013 11:40 am
by bluemoon
Check the wiki PCI
The lower 4 bits are attributes.