Page 1 of 1

PCI enumeration [solved]

Posted: Thu Mar 13, 2008 2:18 pm
by lukem95
hey, can somebody check my code please. It seems right to me, but i'm trying to enumerate the PCI, and load drivers from the data gathered (Well... print a message and _eventually_ enable the driver).

Code: Select all

static PCI_Device_t* pci_getdevice(int bus, int device, int function)
{
  static PCI_Device_t* pci_device;
  unsigned short vendor = 0, deviceid = 0;
  unsigned char classcode = 0, subclass = 0;
  
  if ((vendor = pci_read(bus,device,0,0)) != 0xFFFF)
  {
       deviceid = pci_read(bus,device,0,2);
       classcode = (pci_read(bus,device,0,10) << 4 );
       subclass = (pci_read(bus,device,0,10) >> 4 );   
       
       pci_device->ClassCode = classcode;
       pci_device->SubClass = subclass;
       pci_device->VendorID = vendor;
       pci_device->DeviceID = deviceid;
  }
  pci_device->VendorID = vendor;
  return pci_device;
}

This is the code i'm using the get the Class code etc, and i then switch this using:

Code: Select all

switch(tmp->ClassCode)
                                   {
                                        //Pre-PCI Items
                                        case 0x00:
                                             if(tmp->SubClass == 0x01)
                                                  //Load VGA driver
                                                  kprintf("VGA driver loading (legacy)... \n");
                                        break;
                                        
                                        //Mass storage devices
                                        case 0x01:
                                             if(tmp->SubClass == 0x01)
                                                  //IDE
                                                  kprintf("ATA (IDE) driver loading... [TODO]\n");
                                             if(tmp->SubClass == 0x02)
                                                  //Floppy
                                                  kprintf("Floppy legacy driver loading... [TODO]\n");
                                                  
                                             if(tmp->SubClass == 0x80)
                                                  kprintf("Mass storage device controller driver loading... [TODO]\n");
                                        break;

...

I get 32 entries in the PCI for Qemu, and 16 for bochs (is this right?), but the Class Code is always 0x00.

any thoughts or obvious errors?

thanks, luke

Posted: Thu Mar 13, 2008 5:55 pm
by Combuster
I think one error has to do with this line: (why the left shift?)

Code: Select all

classcode = (pci_read(bus,device,0,10) << 4 ); 
The other error is that you get an power of two amount of devices, which is unrealistic as well. I just ran my own PCI code in QEMU - it gives me 5 devices: 3 intel ones, and two others (I guess they're a cirrus and a creative).

But why it consequently thinks that the classcode is 0, I have no idea. Try printing all vendor:device codes for starters and see if you get meaningful values out of those. You may also want to post your PCI reading code itself.

Re: PCI enumeration

Posted: Fri Mar 14, 2008 4:02 am
by Brendan
Hi,
zaleschiemilgabriel wrote:I see you're from "Cambridge, UK"... I thought that place was filled with geniuses. :roll:
Do you think he's in Cambridge University (e.g. studying architecture), or in the city of Cambridge (e.g. working as a doctor of medicine)?
zaleschiemilgabriel wrote:HINT: Avoid asking people to do your homework on Fridays, Mondays or during the weekend. Fridays are the worst. Mondays are really bad too.
Where was homework mentioned, or what led you to assume it was homework?
zaleschiemilgabriel wrote:Well, it's just not enough to say "please" anymore
I'd like to think "please" is more than enough, especially when combined with a polite and detailed request.

Instead of being rude, you might want to consider refraining from replying if you're not interested in helping...


Cheers,

Brendan

Posted: Fri Mar 14, 2008 6:31 am
by lukem95
erm.. thankyou brendan for your reply... im actually 15, and although i'd say im fairly smart, i am still in secondary school. This is not quite the same standard as Cambridge Uni.

I'll have another look at my code when i get home from school...

thankyou for your help

Re: PCI enumeration

Posted: Fri Mar 14, 2008 6:42 am
by jal
lukem_95 wrote:hey, can somebody check my code please. (...) any thoughts or obvious errors?

Code: Select all

       classcode = (pci_read(bus,device,0,10) << 4 ); 
       subclass = (pci_read(bus,device,0,10) >> 4 );  
You read twice the same value. That's rather inefficient, and although I don't know how the PCI handles it, in general it's not a good idea to read the same hardware register twice and expect the same value. Also I don't understand why you put brackets around the statement (though that's obviously not a problem). I'd do something like this:

Code: Select all

class = pci_read(bus, device, 0, 10);
classcode = class << 4;
subclass = class >> 4;
Since that shifting seemed a bit weird to me, I Googled a bit on class codes, and I found e.g. this:
ibm.com wrote:PCI devices also identify themselves with a class code, identifying roughly what type of function they perform, for instance, storage, or networking. The class code is a 16-bit value; the first 8 bits indicate an overall class, such as "mass storage" or "display;" the second 8 bits can indicate subclasses, such as "SCSI" or "IDE" for mass storage, or "Ethernet" or "Token Ring" for network devices.
So it seems the class code is 2x8 bits, not 2x4 as you treat it. That could be the source of your problem.


JAL

Disclaimer: The author has no knowledge of PCI busses and device enumeration. Don't beat him with a stick if Google found the wrong answers.

Posted: Tue Mar 18, 2008 4:00 pm
by Combuster
*puts in the last nail of the new garden fence*

I don't agree with locking this thread. Instead, tell us wether anything helped you fix the problem in the meantime, or if it still doesn't work.

Posted: Tue Mar 18, 2008 4:21 pm
by lukem95
ok, i rewrote my code. My problem was indeed the issue with me treating it as 4 bits instead of 8. The masking was changed to 8 and the data types altered and this worked correctly.

Thankyou everyone for your help ;)

(and thankyou Combbuster for moving the other half of this thread)

Posted: Thu Mar 20, 2008 2:35 am
by zaleschiemilgabriel
Sorry I was an @$$. :oops: Please don't feed the troll next time.