Is my PCI device listing is valid?

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
osdever
Member
Member
Posts: 492
Joined: Fri Apr 03, 2015 9:41 am
Contact:

Is my PCI device listing is valid?

Post by osdever »

I've decided to implement basic PCI support, so I wrote the code, it works, but I don't know its validity: there's no network interface, no graphics card, almost nothing! Here's my code:

Code: Select all

//PCI support, yes!
#include <arch/i686/pci.h>
#include <arch/i686/io.h>
#include <stdint.h>
#include <stdio.h>
//pci_read_confspc_word(): Returns 16-bit value from PCI Configuration Space of specified device at specified offset.
uint16_t pci_read_confspc_word(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset)
{
	uint32_t addr;
	uint32_t bus32 = bus;
	uint32_t slot32 = slot;
	uint32_t func32 = function;
	addr = (uint32_t)((bus32 << 16) | (slot32 << 11) |
           (func32 << 8) | (offset & 0xfc) | ((uint32_t)0x80000000)); //yes, this line is copied from osdev
	outl(PCI_ADDRESS_PORT, addr);
	return (uint16_t)((inl(PCI_DATA_PORT) >> ((offset & 2) * 8)) & 0xffff); //this too... I'm too lazy to write them
}
static struct {
	uint8_t dev_class, dev_subclass; //added dev_ to prevent errors in C++
	const char *name;
} pci_device_type_strings[] = {
	{0x00, 0x00, "Unknown device"},
	{0x00, 0x01, "VGA-compatible Device"},
	{0x01, 0x00, "SCSI Bus Controller"},
	{0x01, 0x01, "IDE Controller"},
	{0x01, 0x02, "Floppy Disk Controller"},
	{0x01, 0x03, "IPI Bus Controller"},
	{0x01, 0x04, "RAID Controller"},
	{0x01, 0x05, "ATA Controller"},
	{0x01, 0x06, "SATA Controller"},
	{0x01, 0x07, "Serial Attached SCSI Controller"},
	{0x01, 0x80, "Other Mass Storage Controller"},
	{0x02, 0x00, "Ethernet Controller"},
	{0x02, 0x01, "Token Ring Controller"},
	{0x02, 0x02, "FDDI Controller"},
	{0x02, 0x03, "ATM Controller"},
	{0x02, 0x04, "ISDN Controller"},
	{0x02, 0x05, "WorldFip Controller"},
	{0x02, 0x06, "PICMG 2.14 Multi Computing"},
	{0x02, 0x80, "Other Network Controller"},
	{0x03, 0x00, "VGA-compatible Controller"},
	{0x03, 0x01, "XGA Controller"},
	{0x03, 0x02, "3D Controller"},
	{0x03, 0x80, "Other Display Controller"},
	{0x04, 0x00, "Video Device"},
	{0x04, 0x01, "Audio Device"},
	{0x04, 0x02, "Computer Telephony Device"},
	{0x04, 0x80, "Other Multimedia Device"},
	{0x05, 0x00, "RAM Controller"},
	{0x05, 0x01, "Flash Controller"},
	{0x05, 0x80, "Other Memory Controller"},
	{0x06, 0x00, "Host Bridge"},
	{0x06, 0x01, "ISA Bridge"},
	{0x06, 0x02, "EISA Bridge"},
	{0x06, 0x03, "MCA Bridge"},
	{0x06, 0x04, "PCI-to-PCI Bridge"},
	{0x06, 0x05, "PCMCIA Bridge"},
	{0x06, 0x06, "NuBus Bridge"},
	{0x06, 0x07, "CardBus Bridge"},
	{0x06, 0x08, "RACEWay Bridge"},
	{0x06, 0x09, "PCI-to-PCI Bridge (Semi-Transparent)"},
	{0x06, 0x0A, "InfiniBand-to-PCI Host Bridge"},
	{0x06, 0x80, "Other Bridge Device"},
	{0x07, 0x00, "Serial Controller"},
	{0x07, 0x01, "Parallel Port"},
	{0x07, 0x02, "Multiport Serial Controller"},
	{0x07, 0x03, "Generic Modem"},
	{0x07, 0x04, "IEEE 488.1/2 (GPIB) Controller"},
	{0x07, 0x05, "Smart Card"},
	{0x07, 0x80, "Other Communication Device"},
	{0x08, 0x00, "Programmable Interrupt Controller"},
	{0x08, 0x01, "DMA Controller"},
	{0x08, 0x02, "System Timer"},
	{0x08, 0x03, "Real-Time Clock"},
	{0x08, 0x04, "Generic PCI Hot-Plug Controller"},
	{0x08, 0x80, "Other System Peripheral"},
	{0x09, 0x00, "Keyboard Controller"},
	{0x09, 0x01, "Digitizer"},
	{0x09, 0x02, "Mouse Controller"},
	{0x09, 0x03, "Scanner Controller"},
	{0x09, 0x04, "Gameport Controller"},
	{0x09, 0x80, "Other Input Controller"},
	{0x0A, 0x00, "Generic Docking Station"},
	{0x0A, 0x80, "Other Docking Station"},
	{0x0B, 0x00, "i386 CPU"},
	{0x0B, 0x01, "i486 CPU"},
	{0x0B, 0x02, "Pentium CPU"},
	{0x0B, 0x10, "Alpha CPU"},
	{0x0B, 0x20, "PowerPC CPU"},
	{0x0B, 0x30, "MIPS CPU"},
	{0x0B, 0x40, "Co-processor"},
	{0x0C, 0x00, "FireWire Controller"},
	{0x0C, 0x01, "ACCESS.bus Controller"},
	{0x0C, 0x02, "SSA Controller"},
	{0x0C, 0x03, "USB Controller"},
	{0x0C, 0x04, "Fibre Channel"},
	{0x0C, 0x05, "SMBus"},
	{0x0C, 0x06, "InfiniBand"},
	{0x0C, 0x07, "IPMI SMIC Interface"},
	{0x0C, 0x08, "SERCOS Interface"},
	{0x0C, 0x09, "CANbus Interface"},
	{0x0D, 0x00, "iRDA Compatible Controller"},
	{0x0D, 0x01, "Consumer IR Controller"},
	{0x0D, 0x10, "RF Controller"},
	{0x0D, 0x11, "Bluetooth Controller"},
	{0x0D, 0x12, "Broadband Controller"},
	{0x0D, 0x20, "802.11a (Wi-Fi) Ethernet Controller"},
	{0x0D, 0x21, "802.11b (Wi-Fi) Ethernet Controller"},
	{0x0D, 0x80, "Other Wireless Controller"},
	
	{0x00, 0x00, NULL} //here array ends
};
uint8_t pci_get_class(uint8_t bus, uint8_t slot, uint8_t function)
{
	return (uint8_t) (pci_read_confspc_word(bus, slot, function, 5) >> 8) /* shifting to leave only class id in the variable. */;
}
uint8_t pci_get_subclass(uint8_t bus, uint8_t slot, uint8_t function)
{
	return (uint8_t) pci_read_confspc_word(bus, slot, function, 5);
}
uint8_t pci_get_hdr_type(uint8_t bus, uint8_t slot, uint8_t function)
{
	return (uint8_t) pci_read_confspc_word(bus, slot, function, 7);
}
uint16_t pci_get_vendor(uint8_t bus, uint8_t slot, uint8_t function)
{
	return pci_read_confspc_word(bus, slot, function, 0);
}
const char *pci_get_device_type(uint8_t dev_class, uint8_t dev_subclass)
{
	for(int i=0; pci_device_type_strings[i].name != NULL; i++)
		if(pci_device_type_strings[i].dev_class == dev_class && pci_device_type_strings[i].dev_subclass == dev_subclass)
			return pci_device_type_strings[i].name;
	return NULL;
}
void list_pci()
{
	uint8_t clid;
	uint8_t sclid;
	uint16_t vendor;
	for(unsigned bus = 0; bus < 256; bus++)
	{
		for(unsigned slot = 0; slot < 32; slot++)
		{
			unsigned func = 0;
			clid = pci_get_class(bus, slot, func);
			sclid = pci_get_subclass(bus, slot, func);
			vendor = pci_get_vendor(bus, slot, func);
			if(clid != 0xFF && vendor != 0xFFFF)
				printf("Vendor: 0x%x, device: %s %d %d\n", vendor, pci_get_device_type(clid, sclid), sclid, clid);
			if((pci_get_hdr_type(bus, slot, func) & 0x80) == 0)
			for(func = 1; func < 8; func++)
			{
				clid = pci_get_class(bus, slot, func);
				sclid = pci_get_subclass(bus, slot, func);
				vendor = pci_get_vendor(bus, slot, func);
				if(clid != 0xFF && vendor != 0xFFFF)
					printf("Vendor: 0x%x, device: %s %d %d\n", vendor, pci_get_device_type(clid, sclid), sclid, clid);
			}
		}
	}
}
Output on QEMU doesn't seems to be valid, on Bochs some magic happens: output looks valid, but only if I add dev_class++; to pci_get_device_type. QEMU and Bochs output is in post.
Attachments
QEMU
QEMU
Screenshot_20161008_212548.png (7.68 KiB) Viewed 3378 times
Bochs
Bochs
Screenshot_20161008_212439.png (8.11 KiB) Viewed 3378 times
Developing U365.
Source:
only testing: http://gitlab.com/bps-projs/U365/tree/testing

OSDev newbies can copy any code from my repositories, just leave a notice that this code was written by U365 development team, not by you.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Is my PCI device listing is valid?

Post by Octacone »

I don't see anything weird in there. Because different emulators have different devices on different locations of different types.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
osdever
Member
Member
Posts: 492
Joined: Fri Apr 03, 2015 9:41 am
Contact:

Re: Is my PCI device listing is valid?

Post by osdever »

octacone wrote:I don't see anything weird in there. Because different emulators have different devices on different locations of different types.
I know, but is listing on QEMU is valid? You have network controllers and more on your scrs, but I'm not.
Developing U365.
Source:
only testing: http://gitlab.com/bps-projs/U365/tree/testing

OSDev newbies can copy any code from my repositories, just leave a notice that this code was written by U365 development team, not by you.
User avatar
osdever
Member
Member
Posts: 492
Joined: Fri Apr 03, 2015 9:41 am
Contact:

Re: Is my PCI device listing is valid?

Post by osdever »

Added network controller in QEMU args, now it found it, but it displays as IPI Bus Controller.
Developing U365.
Source:
only testing: http://gitlab.com/bps-projs/U365/tree/testing

OSDev newbies can copy any code from my repositories, just leave a notice that this code was written by U365 development team, not by you.
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: Is my PCI device listing is valid?

Post by jnc100 »

Your vendor ID is correct, but your class and subclass IDs are wrong. In particular, you are probably using the wrong offset for your pci read function. If you are using the pciConfigReadWord function from the wiki page, you probably want offset 10 for this 16 bit value (rather than 5 as you are using).

Regards,
John.
User avatar
osdever
Member
Member
Posts: 492
Joined: Fri Apr 03, 2015 9:41 am
Contact:

Re: Is my PCI device listing is valid?

Post by osdever »

jnc100 wrote:Your vendor ID is correct, but your class and subclass IDs are wrong. In particular, you are probably using the wrong offset for your pci read function. If you are using the pciConfigReadWord function from the wiki page, you probably want offset 10 for this 16 bit value (rather than 5 as you are using).

Regards,
John.
Thanks! I thought that it uses offset in words, not bytes ;)
Developing U365.
Source:
only testing: http://gitlab.com/bps-projs/U365/tree/testing

OSDev newbies can copy any code from my repositories, just leave a notice that this code was written by U365 development team, not by you.
User avatar
osdever
Member
Member
Posts: 492
Joined: Fri Apr 03, 2015 9:41 am
Contact:

Re: Is my PCI device listing is valid?

Post by osdever »

It works! Thanks.
Attachments
Screenshot_20161009_105559.png
Screenshot_20161009_105559.png (2.67 KiB) Viewed 3281 times
Developing U365.
Source:
only testing: http://gitlab.com/bps-projs/U365/tree/testing

OSDev newbies can copy any code from my repositories, just leave a notice that this code was written by U365 development team, not by you.
Post Reply