flat assembler
Message board for the users of flat assembler.

Index > OS Construction > PCI Configuration Space 16bit Access

Author
Thread Post new topic Reply to topic
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC 24 Jul 2011, 18:35
While testing my code I found a particularly nasty issue with PCI Configuration Space within VBox and VMware: When reading a WORD value it always reads the low WORD. for example when reading the DeviceID alone it ends up giving you the VendorID instead. this effectively neutralizes any 16-bit PCI Configuration Space access.


BAiC

edit: tested on hardware since first post and has the same result so it's not just the VMs.


Last edited by BAiC on 24 Jul 2011, 19:13; edited 1 time in total
Post 24 Jul 2011, 18:35
View user's profile Send private message Visit poster's website Reply with quote
DJ Mauretto



Joined: 14 Mar 2007
Posts: 464
Location: Rome,Italy
DJ Mauretto 24 Jul 2011, 18:47
Stupid Emulator Wink

_________________
Nil Volentibus Arduum Razz
Post 24 Jul 2011, 18:47
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 24 Jul 2011, 19:01
Did you report it to developers?
Post 24 Jul 2011, 19:01
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC 24 Jul 2011, 19:12
I just found it a few minutes ago.

I tested it on real hardware and I'm getting the same effect.
Post 24 Jul 2011, 19:12
View user's profile Send private message Visit poster's website Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC 24 Jul 2011, 19:17
this should make for some real fun times (sarcasm) setting up the Command Register or responding to interrupts since some of the bits are Read Only, others are Write-Complement and others are normal Write.
Post 24 Jul 2011, 19:17
View user's profile Send private message Visit poster's website Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 25 Jul 2011, 06:48
I'm pretty sure that's correct as you're supposed to use 32bit accesses on dword boundaries (and so masking off the lsb 2 bits will always give you the lo word for non-aligned accesses).

You can actually use 32bit registers in 16bit code for this.
Post 25 Jul 2011, 06:48
View user's profile Send private message Reply with quote
DJ Mauretto



Joined: 14 Mar 2007
Posts: 464
Location: Rome,Italy
DJ Mauretto 25 Jul 2011, 08:41
Post your code please Wink

_________________
Nil Volentibus Arduum Razz
Post 25 Jul 2011, 08:41
View user's profile Send private message Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC 25 Jul 2011, 20:27
So I did a bit more thinking on the topic -- since the docs don't provide anything! -- and I figured out the correct way to access config space.

Code:
pci.r16:
        
        pushf;PCI Config Space is transactional, so turn off interrupts briefly.
        cli
            
            ;on entry EAX has the Address already prepared.
            mov edx, PCI.Bus.ADDR
            out dx, eax
            and eax, 2;the I/O Port actually plays a role.
            lea edx, [rdx+rax+PCI.Bus.DATA-PCI.Bus.ADDR]
            insw
            
        popf
        
    ret    
is the correct way.
Post 25 Jul 2011, 20:27
View user's profile Send private message Visit poster's website Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC 25 Jul 2011, 22:33
cod3b453: DWORD boundaries wasn't the issue.

When issuing the Address Phase of the Transaction a DWORD-size "Window" appears at the DATA Port regardless of what the low 2 bits of the Address was (actually, the lowest bit determines whether it's a Type 0 or Type 1 Transaction so Byte Access can't occur this way). As I've now found out, the Address must influence the Port Address in order to access the other bytes.

my Enumerator (a part of Mathis) uses DWORD blocks in order to retrieve Config Space data and store it inside memory for the users of that data. Reading it from the in-memory copy is considerably simpler.
Post 25 Jul 2011, 22:33
View user's profile Send private message Visit poster's website Reply with quote
DJ Mauretto



Joined: 14 Mar 2007
Posts: 464
Location: Rome,Italy
DJ Mauretto 26 Jul 2011, 10:35
Hello...
Your code is unreadable Laughing
Anyway...
Code:

; Eax = Bus, Device, Function, Register


; Select bus device function and register

mov dx,0cf8h
out  dx,eax

; now you can read byte,word and dword quantity in this way:

; Read Byte at any offset

mov dx,0cfch
in al,dx                       ; read byte at offset 0

add dx,1
in al,dx                       ; read byte at offset 1

add dx,1
in al,dx                       ; read byte at offset 2

add dx,1
in al,dx                       ; read byte at offset 3

; read word at offset 0 and 2

mov dx,0cfch
in ax,dx                      ; read word at offset 0

add dx,2                     ; read word at offset 2
in ax,dx

; of course you can rea all 4 bytes

mov dx,0cfch
in eax,dx

    
Wink

_________________
Nil Volentibus Arduum Razz
Post 26 Jul 2011, 10:35
View user's profile Send private message Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC 27 Jul 2011, 02:01
after fixing the problem with my code these are the corrected versions.. I've posted the full code (Mathis) at http://board.flatassembler.net/topic.php?t=12856.

Note: these functions are using macros for I/O instructions (in->inb/w/d) they are declared in the other Mathis files.

Code:
    ;I/O String Read, DWORD unit, of PCI Configuration Space.
   .R:
        
        pushfq
        cli
            
            mov edx, PCI.Bus.ADDR
            oud
            add edx, PCI.Bus.DATA-PCI.Bus.ADDR
            insd
            
        popfq
        
    ret
    
    ;I/O String Read, WORD unit, of PCI Configuration Space.
   .R16:
        
        pushfq
        cli
            
            psh rax
            and eax,-4
            mov edx, PCI.Bus.ADDR
            oud
            pop rax
            and eax, 2
            lea edx, [rdx+rax+PCI.Bus.DATA-PCI.Bus.ADDR]
            insw
            
        popfq
        
    ret
    
    ;I/O String Read, BYTE unit, of PCI Configuration Space.
   .R8:
        
        pushfq
        cli
            
            psh rax
            and eax,-4
            mov edx, PCI.Bus.ADDR
            oud
            pop rax
            and eax, 3
            lea edx, [rdx+rax+PCI.Bus.DATA-PCI.Bus.ADDR]
            insb
            
        popfq
        
    ret
    
   .Read32:
        
        pushfq
        cli
            
            mov edx, PCI.Bus.ADDR
            oud
            add edx, PCI.Bus.DATA-PCI.Bus.ADDR
            ind 
            
        popfq
        
    ret
    
   .Read16:
        
        pushfq
        cli
            
            psh rax
            and eax,-4
            mov edx, PCI.Bus.ADDR
            oud
            pop rax
            and eax, 2
            lea edx, [rdx+rax+PCI.Bus.DATA-PCI.Bus.ADDR]
            inw
            
        popfq
        
    ret
    
   .Read8:
        
        pushfq
        cli
            
            psh rax
            and eax,-4
            mov edx, PCI.Bus.ADDR
            oud
            pop rax
            add edx, PCI.Bus.DATA-PCI.Bus.ADDR
            inb
            
        popfq
        
    ret
    
   .W:
        
        pushfq
        cli
            
            mov edx, PCI.Bus.ADDR
            oud
            add edx, PCI.Bus.DATA-PCI.Bus.ADDR
            outsd
            
        popfq
        
    ret
    
   .W16:
        
        pushfq
        cli
            
            psh rax
            and eax,-4
            mov edx, PCI.Bus.ADDR
            oud
            pop rax
            and eax, 2
            lea edx, [rdx+rax+PCI.Bus.DATA-PCI.Bus.ADDR]
            outsw
            
        popfq
        
    ret
    
   .W8:
        
        pushfq
        cli
            
            mov edx, PCI.Bus.ADDR
            oud
            and eax, 3
            lea edx, [rdx+rax+PCI.Bus.DATA-PCI.Bus.ADDR]
            outsb
            
        popfq
        
    ret
    
   .Write32:
        
        pushfq
        cli
            
            mov edx, PCI.Bus.ADDR
            oud
            add edx, PCI.Bus.DATA-PCI.Bus.ADDR
            mov eax, ecx
            oud
            
        popfq
        
    ret
    
   .Write16:
        
        pushfq
        cli
            
            psh rax
            and eax,-4
            mov edx, PCI.Bus.ADDR
            out  dx, eax
            
            pop rax
            and eax, 2
            lea edx, [rdx+rax+PCI.Bus.DATA-PCI.Bus.ADDR]
            mov eax, ecx
            out  dx, ax
            
        popfq
        
    ret
    
   .Write8:
        
        pushfq
        cli
            
            psh rax
            and eax,-4
            mov edx, PCI.Bus.ADDR
            oud
            pop rax
            and eax, 3
            lea edx, [rdx+rax+PCI.Bus.DATA-PCI.Bus.ADDR]
            mov eax, ecx
            oub
            
        popfq
        
    ret    
I also have macro-versions which conditionally place in the "pushfq / cli" operations (those are at the end of 'macros.asm').
Post 27 Jul 2011, 02:01
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
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 vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.