Page 1 of 1

Harddrives not being detected on PCI

Posted: Sat Jun 04, 2011 9:16 am
by Tobba
According to this article on the wiki, harddrives should appear on the PCI bus, but for me, all my code finds on the PCI bus is:

Code: Select all

VendorID: 0x00008086 DeviceID: 0x00008086 Class: 0x00000006 Subclass: 0x00000000
VendorID: 0x00008086 DeviceID: 0x00008086 Class: 0x00000006 Subclass: 0x00000001
First is a host bridge and second is a PCI-to-ISA bridge
I've also set bochs to emulate an NE2K NIC and a SB16 sound card
I assume that their all being emulated as ISA, but it makes me think my code for PCI is all wrong, or the article

Code:

Code: Select all

typedef struct
{
	// TODO
	unsigned short vendorID;
	unsigned short deviceID;
} pci_config;

typedef struct
{
	unsigned char bus;
	unsigned char slot;
	unsigned char config[256];
} pci_device;

pci_device *pci_devices;

unsigned char pciConfigReadByte(unsigned short bus, unsigned short slot, unsigned short func, unsigned short offset)
{
	unsigned long address;
	unsigned long lbus = (unsigned long)bus;
	unsigned long lslot = (unsigned long)slot;
	unsigned long lfunc = (unsigned long)func;
	unsigned short tmp = 0;
 
	/* create configuration address as per Figure 1 */
	address = (unsigned long)((lbus << 16) | (lslot << 11) | (lfunc << 8) | (offset & 0xFC) | 0x80000000);

	outd(0xCF8, address);

	return (unsigned char)((ind(0xCFC) >> ((offset & 3) << 3)) & 0xFF);
}

unsigned short pciConfigReadWord(unsigned short bus, unsigned short slot, unsigned short func, unsigned short offset)
{
	unsigned long address;
	unsigned long lbus = (unsigned long)bus;
	unsigned long lslot = (unsigned long)slot;
	unsigned long lfunc = (unsigned long)func;
	unsigned short tmp = 0;
 
	/* create configuration address as per Figure 1 */
	address = (unsigned long)((lbus << 16) | (lslot << 11) | (lfunc << 8) | (offset & 0xFC) | 0x80000000);

	outd(0xCF8, address);

	return (unsigned short)((ind(0xCFC) >> ((offset & 2) << 3)) & 0xFFFF);
}

unsigned long pciConfigReadDWord(unsigned short bus, unsigned short slot, unsigned short func, unsigned short offset)
{
	unsigned long address;
	unsigned long lbus = (unsigned long)bus;
	unsigned long lslot = (unsigned long)slot;
	unsigned long lfunc = (unsigned long)func;
	unsigned short tmp = 0;
 
	/* create configuration address as per Figure 1 */
	address = (unsigned long)((lbus << 16) | (lslot << 11) | (lfunc << 8) | (offset & 0xFC) | 0x80000000);

	outd(0xCF8, address);

	return ind(0xCFC);
}

void init_pci()
{
	unsigned short bus;
	unsigned short slot;
	for (bus = 0; bus < 0xFF; bus++)
	{
		for (slot = 0; slot < 0x20; slot++)
		{
			if (pciConfigReadDWord(bus, slot, 0, 0) != 0xFFFFFFFF)
			{
				pci_device device;
				for (i = 0; i < 0x40; i++)
				{
					((unsigned long*)device.config)[i] = pciConfigReadDWord(bus, slot, 0, i << 2);
				}
				puts("VendorID: ");
				puth(((unsigned short*)device.config)[0]);
				puts(" DeviceID: ");
				puth(((unsigned short*)device.config)[0]);
				puts(" Class: ");
				puth(device.config[0x0B]);
				puts(" Subclass: ");
				puth(device.config[0x0A]);
				putch('\n');
			}
		}
	}
}
(Messy, I know)

Is it my code thats all wrong, the article wrong, or is it something else?

Re: Harddrives not being detected on PCI

Posted: Sat Jun 04, 2011 10:31 am
by shikhin
Hi,

I was just wondering whether you are clear what the third argument of the following is meant for:

Code: Select all

unsigned long pciConfigReadDWord(unsigned short bus, unsigned short slot, unsigned short func, unsigned short offset)
unsigned short pciConfigReadWord(unsigned short bus, unsigned short slot, unsigned short func, unsigned short offset)
unsigned char pciConfigReadByte(unsigned short bus, unsigned short slot, unsigned short func, unsigned short offset)


Each PCI Configuration address consists of the following format:
Enable Bit (Bit 31) Reserved (Bit 24-30) Bus Number (Bit 16 - 23) Device Number (Bit 11 - 15) Function Number (Bit 8 - 10) Register Number (Bit 2 - 7) 00 (Bit 0 - 1)
Yes, you guessed that right. This means that the Bus Number can range from 0x00 - 0xFF, the Device number can range from 0x00 - 0x20, and the function number can range from 0x00 - 0x07. But before checking all the 8 functions of the specific device, you should first check if the device even supports functions. This can be found out by checking if bit 7 of the Header Type is set; if set, it supports multiple functions, else only a single function (0x00). [source: http://wiki.osdev.org/PCI#PCI_Device_Structure]

Perhaps you could clear out every doubt using the following: http://wiki.osdev.org/PCI#Configuration_Mechanism_.231 rather than posting back. 8)

Regards,
Shikhin

Re: Harddrives not being detected on PCI

Posted: Sat Jun 04, 2011 11:42 am
by Combuster
It's much simpler:

Code: Select all

            puts("VendorID: ");
            puth(((unsigned short*)device.config)[0]);
            puts(" DeviceID: ");
            puth(((unsigned short*)device.config)[0]);
Since when is the vendor id stored at the same location as the device id? :wink:

Re: Harddrives not being detected on PCI

Posted: Sat Jun 04, 2011 12:44 pm
by Tobba
Combuster wrote:It's much simpler:

Code: Select all

            puts("VendorID: ");
            puth(((unsigned short*)device.config)[0]);
            puts(" DeviceID: ");
            puth(((unsigned short*)device.config)[0]);
Since when is the vendor id stored at the same location as the device id? :wink:
Ever since typos existed

Either way i got it fixed now, I must have missed something about the functions on devices