No ATA Controller in PCI Configuration Space?

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
nakst
Member
Member
Posts: 51
Joined: Sun Jan 17, 2016 7:57 am

No ATA Controller in PCI Configuration Space?

Post by nakst »

Hello,
I've created some simple PCI configuration space scanning code for my kernel following the guidance of PCI, although I'm a tad concerned at the lack of an ATA controller (class 1, subclass 5) in the output on Qemu, Bochs and VirtualBox. On VirtualBox I get a SATA controller listed (class 1, subclass 6), but even though I have an IDE controller specified in the machine settings the ATA controller does not show up. I don't get a SATA controller listed in Bochs or Qemu, but I don't think I've told them to make one. I have not tried it yet on real hardware, as I want to make sure it works in emulators first. I know the ports for ATA are pretty much standardised, but according to the DMA page on the wiki I need to know BAR4 of the disk controller, so this is a concern as I am planning to use DMA with ATA.

Here is the code I'm using (C++)

Code: Select all

void pciInit() {
	for (int bus = 0; bus < 256; bus++) 
		for (int device = 0; device < 32; device++) {
			int vendorID = pciConfigRead(bus, device, 0, 0) & 0xFFFF;
			if (vendorID == PCI_INVALID_VENDOR_ID) continue;

			int headerType = 0xFF & (pciConfigRead(bus, device, 0, 0xC) >> 16);
			int functions = (headerType & 0x80) ? 8 : 1;

			for (int function = 0; function < functions; function++)
				if ((pciConfigRead(bus, device, function, 0) & 0xFFFF) != 0xFFFF) {
					int vendorID = pciConfigRead(bus, device, 0, 0) & 0xFFFF;
					int deviceID = (pciConfigRead(bus, device, 0, 0) >> 16) & 0xFFFF;
					int classCode = (pciConfigRead(bus, device, 0, 8) >> 24) & 0xFF;
					int subclassCode = (pciConfigRead(bus, device, 0, 8) >> 16) & 0xFF;

					printf("Detected device: vendor 0x%X\tdevice 0x%X  \tclass 0x%X\tsubclass 0x%X\n",
							vendorID, deviceID, classCode, subclassCode);
				}
		}
}
I run Qemu with: qemu-system-x86_64 -drive file=drive,format=raw,media=disk,index=0 -m 2048

Attached below is a screenshot of the output on Qemu, Bochs and VirtualBox.

My questions:
1. Is my PCI scanning code correct? Should I be initialising something else first?
2. How can I get it to find the ATA controller? It is not listed in emulators?
3. If I can't find the controller, how should I get the information for DMA? ACPI?

Thanks for your help. :D
Last edited by nakst on Tue Oct 26, 2021 9:20 am, edited 1 time in total.
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: No ATA Controller in PCI Configuration Space?

Post by BrightLight »

In my ATA code, I search for PCI class/subclass 1/1 (0x0101) and it runs on QEMU, Bochs and VirtualBox.
Although I don't see any class/subclass 1/1 devices in your screenshot... Are you sure there's an IDE controller?
In QEMU, just do:

Code: Select all

qemu-system-x86_64 yourdiskimage.img
If you cannot use DMA in any way, throw an error or fall back to PIO.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
User avatar
nakst
Member
Member
Posts: 51
Joined: Sun Jan 17, 2016 7:57 am

Re: No ATA Controller in PCI Configuration Space?

Post by nakst »

omarrx024 wrote:In my ATA code, I search for PCI class/subclass 1/1 (0x0101) and it runs on QEMU, Bochs and VirtualBox.
Although I don't see any class/subclass 1/1 devices in your screenshot... Are you sure there's an IDE controller?
In QEMU, just do:

Code: Select all

qemu-system-x86_64 yourdiskimage.img
If you cannot use DMA in any way, throw an error or fall back to PIO.
Okay, I tried running Qemu with this command but I got exactly the same output as before. Do you know which bus and device you find the controller on with Qemu?
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: No ATA Controller in PCI Configuration Space?

Post by BrightLight »

Is your PCI code for searching functions correct?
Did you try running QEMU with:

Code: Select all

-monitor stdio
And then running "info pci"? Is there an IDE controller?
From my kernel debug messages:

Code: Select all

[ata] looking for PCI IDE controller...
[ata] done, found IDE controller at PCI slot 00:01:01
So in Bochs, QEMU and VirtualBox, the IDE controller is at bus 0, device 1, function 1.
EDIT: I just noticed: why are you reading the PCI vendor/device/class codes only with the bus and device? Why don't you pass the function?
You know your OS is advanced when you stop using the Intel programming guide as a reference.
User avatar
nakst
Member
Member
Posts: 51
Joined: Sun Jan 17, 2016 7:57 am

Re: No ATA Controller in PCI Configuration Space?

Post by nakst »

Ahhhh, I just noticed it in a debugger. I'd gone through the code several times but only just noticed it.
Thanks for your help! I'm getting the correct class and subclass codes now!
Sometimes having someone else proofread you code is really useful!
User avatar
nakst
Member
Member
Posts: 51
Joined: Sun Jan 17, 2016 7:57 am

Re: No ATA Controller in PCI Configuration Space?

Post by nakst »

To anyone who wants it, here is the final (and working!) code:

Code: Select all

	for (int bus = 0; bus < 256; bus++)
		for (int device = 0; device < 32; device++)
			for (int function = 0; function < 8; function++) {
				int vendorID = (pciConfigRead(bus, device, function, 0) & 0xFFFF);
				if (vendorID != PCI_INVALID_VENDOR_ID) {
					int deviceID = (pciConfigRead(bus, device, function, 0) >> 16) & 0xFFFF;
					int classCode = (pciConfigRead(bus, device, function, 8) >> 24) & 0xFF;
					int subclassCode = (pciConfigRead(bus, device, function, 8) >> 16) & 0xFF;

					Device device;
					device.type = DEVICE_TYPE_UNKNOWN;
					device.classCode = classCode;
					device.subclassCode = subclassCode;

					if (classCode == 6)
						device.type = DEVICE_TYPE_BRIDGE_DEVICE;
					else if (classCode == 3 && subclassCode == 0)
						device.type = DEVICE_TYPE_VGA_CONTROLLER;
					else if (classCode == 2 && subclassCode == 0)
						device.type = DEVICE_TYPE_ETHERNET_CONTROLLER;
					else if (classCode == 0xC && subclassCode == 3)
						device.type = DEVICE_TYPE_USB;
					else if (classCode == 1 && subclassCode == 6)
						device.type = DEVICE_TYPE_SATA;
					else if (classCode == 4 && subclassCode == 1)
						device.type = DEVICE_TYPE_AUDIO;
					else if (classCode == 1 && subclassCode == 1)
						device.type = DEVICE_TYPE_IDE;

					ADD_DARRAY(state.devices, device);
				}
			}
And the VirtualBox output is attached below.
Post Reply