OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Sep 25, 2018 5:21 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: PCI gives strange values
PostPosted: Tue Sep 11, 2018 10:39 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 62
Good day! PCI gives me strange values. On 65025 devices is vendorID 3327, deviceID 0, classcode 0, subclass 0 and progIF 12. I use Virtualbox. Please what it is? My code is in https://github.com/Klaykap/LightningOS/issues/1


Top
 Profile  
 
 Post subject: Re: PCI gives strange values
PostPosted: Thu Sep 13, 2018 7:38 pm 
Offline
Member
Member
User avatar

Joined: Sun Sep 19, 2010 10:05 pm
Posts: 1031
From a quick look at your code, I think

Code:
tmp = (uint16_t)((inl(0xCFC) >> ((offset & 2) * 8)) & 0xffff);


Should be

Code:
tmp = (uint16_t)((inl(0xCFC) >> ((offset & 1) == 0 ? 8 : 0)) & 0xffff);


Or something like that.

_________________
Project: OZone
Source: GitHub
Current Task: .NET Core Runtime (C64)

"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott


Top
 Profile  
 
 Post subject: Re: PCI gives strange values
PostPosted: Sat Sep 15, 2018 11:26 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 62
Thank you, I change code but output is now:
vendorID 12
deviceID 12
classcode 0
subclass 12
progIF 0
on all 65025 slots.


Top
 Profile  
 
 Post subject: Re: PCI gives strange values
PostPosted: Sat Sep 15, 2018 1:54 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 457
Location: USA
Hi,

When reading the PCI space, you need to keep a few things in mind.

The read register is a dword register, but can be read as a byte, word, or dword, as well as reading any one of the bytes within the dword.

For example, the two lines below produce the exact same results:

word = inpw(PCI_DATA + 2);
word = inpd(PCI_DATA) >> 16;

Therefore, you can read any byte, word, or dword at any offset in the PCI space, with the understanding that you cannot read across a dword boundary. For example, you cannot do:

dword = inpd(PCI_DATA + 2);

expecting to read the high word of the first dword and the low word of the next dword.

With this in mind, the following lines are all valid:

byte = inpb(PCI_DATA + 0);
byte = inpb(PCI_DATA + 1);
byte = inpb(PCI_DATA + 2);
byte = inpb(PCI_DATA + 3);
word = inpw(PCI_DATA + 0);
word = inpw(PCI_DATA + 1);
word = inpw(PCI_DATA + 2);
dword = inpd(PCI_DATA + 0);

However, the following lines are *not* valid:

byte = inpb(PCI_DATA + x); // where x > 3
word = inpw(PCI_DATA + x); // where x > 2
dword = inpd(PCI_DATA + x); // where x > 0

Now, take this in to mind and how about you do the following:

Code:
  pci_read_dword(..., ..., offset)
   begin
     if (offset > 0) then
       begin
         return (pci_read_word(offset) << 0) | (pci_read_word(offset) << 16)
       end
     else
       return dword
   end

Then pci_read_word() does the same thing, but for bytes. i.e.: if the word offset would cross a dword boundary, it calls pci_read_byte twice.

Do you get the idea?

If the current sized read will read across the dword boundary, call the smaller sized read twice, else just read in the sized value.

For example, a dword read from offset 2 in the config space will actually do:
Code:
  read_pci_dword calls:
     read_pci_word(offset + 0)  // offset = 2
     read_pci_word(offset + 2)  // offset = 2

How above a dword read from offset 3?
Code:
  read_pci_dword calls:
     read_pci_word calls
        read_pci_byte(offset + 0)  // offset = 3
        read_pci_byte(offset + 1)  // offset = 3
     read_pci_word(offset + 2)     // offset = 3

Two more things:
1) If the first function of a device returns 0xFFFF as the vendor ID, the remaining functions of this device are not valid. They, infact, might return other values, though since the first function returned 0xFFFF, these functions are to be ignored.
2) The first function has a bit in the header that states whether the remaining functions are valid. If this bit indicates there are no more functions, you must skip the remaining 7 functions while enumerating the PCI. As an example, I have an ATA device controller that will return the same data for all 8 functions read even though there is only one valid function. If your PCI enumerator didn't ignore the remaining 7 functions, you might think you have 8 ATA controllers at this device...

Does this help,
Ben
- http://www.fysnet.net/osdesign_book_series.htm


Top
 Profile  
 
 Post subject: Re: PCI gives strange values
PostPosted: Tue Sep 18, 2018 7:55 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 457
Location: USA
Since you didn't reply yet, either you fixed the problem and haven't been able to stop since, or you still are having problems and have pulled all your hair out thinking about it.

How are you doing?

Ben


Top
 Profile  
 
 Post subject: Re: PCI gives strange values
PostPosted: Thu Sep 20, 2018 11:13 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 62
Sorry, but I did not understand as I do that the methods pci_read_* (in PCI on the wikipage is only pci_read_word) I can't program in Pascal . Please how is done in C?


Top
 Profile  
 
 Post subject: Re: PCI gives strange values
PostPosted: Thu Sep 20, 2018 1:11 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 457
Location: USA
Klakap wrote:
Sorry, but I did not understand as I do that the methods pci_read_* (in PCI on the wikipage is only pci_read_word) I can't program in Pascal . Please how is done in C?

Sorry, I won't write the code for you.

The wiki gives an excellent example of reading a word from a given address. It should be fairly simple to modify it to read a byte or a dword.

Remember, when you write the bitmap to the ADDRESS register, the PCI bus will populate the DATA register with a 32-bit value read from the dword offset specified by the bit map written to the ADDRESS register. It is up to your code to extract a byte, word, or the whole dword from this register by either reading the register as an 8-bit byte, a 16-bit word, or a 32-bit dword. The architecture allows you to read a word from DATA + 0, DATA + 1, or DATA + 2, for example. Or you can read the whole 32-bit dword then AND/SHR the result to get the smaller sized value.

However, the point is, the PCI BUS will only populate the register with DWORDs on DWORD boundaries. You cannot read a dword from PCI Config Space byte offset 2. If you wish to read a dword from this offset, you must tell the PCI bus to read the dword at offset 0, extract the word at offset 2, *and* read the dword from offset 4 (the second dword), then extract the remaining word from this value to combine to create the dword you wish to read.

Here is a figure from Chapter 2 of my USB book:

Image

Assuming each is in little ending format:

Example 1 shows that if I wish to read a byte from PCI Config Space byte offset 20, which is the first byte of Dword 5, I must tell the PCI bus to read the dword at DWORD 5. Then I can extract the byte by either reading a byte from the register (DATA + 0, in this case), or reading the whole dword register and ANDing the 32-bit value to extract the 8-bit result.

Example 2 shows that if I wish to read a word from PCI Config Space byte offset 30, which is the higher word of Dword 7, I must tell the PCI bus to read the dword at DWORD 7. Then I can extract the word by either reading a word from the register (DATA + 2, in this case), or reading the whole dword register and SHRing the 32-bit value to extract the 16-bit result.

Example 3 shows that if I wish to read a dword from PCI Config Space byte offset 34, I *must* read from the PCI bus twice to get the result dword value. I *must* read from Dword 8, extract the high word, placing it in the low word of my result value, then I *must* read from Dword 9, extracting the low word and placing it in the high word of my resultant value.

This is quite confusing, but with a little reading and understanding, it will get quite easy, quite quickly.

My point to this and my previous post is that if you write three routines, a read_dword, a read_word, and a read_byte routine, you can call either of them with a byte offset to the value you wish to read. Then if the dword or word routine calculates that it would be reading across a dword boundary, it can call the lesser-sized routine twice to extract this value, of course knowing that a byte read will not cross a dword boundary, because you are reading a byte from a byte offset.

Therefore, if I wish to read a dword from byte offset 34, as in the example above, I call my read_dword routine with an offset value of 34. My dword routine does a:
Code:
  if ((offset + 4) % 4) > 0) {
or
  if ((offset & 3) > 0) {
or
  if (any other way to know if we would cross a boundary) {
     low_word = read_word(offset + 0);
     high_word = read_word(offset + 2);
     return (high_word << 16) | low_word;
  } else
     return dword_read_from_DATA_register;

The read_word routine does the same thing, calling two byte-reads if necessary.

This technique lets me read a dword from any byte offset within the PCI Config space by calling only read_dword(), allowing the read_dword() routine to "farm" out the necessary 16-bit reads, then allowing read_word() "farm" out the necessary 8-bit reads.

Does this make any sense? Clear as mud?

Ben
- http://www.fysnet.net/osdesign_book_series.htm


Top
 Profile  
 
 Post subject: Re: PCI gives strange values
PostPosted: Sat Sep 22, 2018 10:15 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 62
Thank you for advice, I will try to do a driver for the PCI.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: alberinfo and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group