Page 1 of 1

PCI program???

Posted: Tue Nov 11, 2008 5:55 pm
by Sam111
I don't know why the print pci function doesn't work.
It always prints a blank space and then a 2 dotted U.

If I increase the amount of characters I print out it just prints garbage.

Can anybody see the problem here with the int 10.

I set es:bp -> to vendor.

As a test I put vendor = 'JB'
Thanks for any help .
Does it have to do with bits 32 or bits 16
Because I never used int 10 in a 32 bit program
Also I am just running it under ms dos on windows xp.

Code: Select all


[BITS 32]

;compiled with nasm -f obj PCIdev.asm
; linked with tlink PCIdev.obj

segment data

BUS_NUMBER           db 0                  ; bus number 1 to 256 are valid values
DEVICE_NUMBER        db 29               ;device number 1 - 32 are vaild values
FUNCTION_NUMBER      db 7               ; function number 1-8 are vaild values
REGISTER_NUMBER      db 0               ; register number 1-64 are vaild values
vendor               db 'JB'                   ; just test values print should print JB but it doesn't it prints a blank and a weird 2 dot U  ascii 154
segment code

..start:

jmp main 

;PCI_FUNC is a function that returns a word from the pci configuration space
;using  data in BUS_NUMBER , DEVICE_NUMBER , FUNCTION_NUMBER , REGISTER_NUMBER 
;output is in ax
;registers effected are eax 
;Basically the function just send a 32 bit number to the configuration address and reads a word from the data address of the pci

PCI_FUNC:

push edx                            ;  saves your data that was previously in edx before using edx  
mov eax , 0                         ; initalize the register to zero
mov edx , 0                         ; initalize the register to zero

mov eax , 1                         ; mov 00000001 into  eax
shl eax , 31                        ; shift the 1 to the top most bit 10000000

mov edx , BUS_NUMBER                ; mov the bus number byte into  edx
shl edx , 16                        ;  move the bus number to bits 23 - 16

or eax , edx                        ; put bus number in eax

xor edx , edx                       ; zero out edx

mov edx , DEVICE_NUMBER             ; mov device number into edx
shl edx , 11                        ; shift the device number to bits 15-11

or eax , edx                        ; put device number in eax

xor edx , edx                       ; zero out edx

mov edx , FUNCTION_NUMBER           ; move  the function number into edx
shl edx , 8                         ; shift function number to bits  10 - 8
or eax , edx                        ; put function number in eax

xor edx , edx                       ; zero out edx

mov edx , REGISTER_NUMBER           ; move register number into edx
shl edx , 2                         ; shift register number to bits 7-2
or eax , edx                        ; put register number in eax

xor edx , edx                       ; zero out edx for the hell of it to clean it out

mov dx , 0xCF8                      ; move the configuration address for the pci into dx 
out dx , eax                        ;  send the data in eax to the configuration address port
mov dx , 0xCFC                      ; move the configuration data address into dx
in  ax , dx                         ; read a word  from the configuration data address  0xCF8

pop edx                             ; returns your previously saved edx value back to edx
 
ret 

PRINT_PCI:  ;this function prints the 2 bytes of the vendor id 

mov ax , ds
mov es , ax  ; make sure es points to the same segment as data segment
mov cx , 2  ; output 2 bytes  vendor is a word
mov bx , 000Fh ; make text color attrubites ...etc white
mov ax , 1300h ; prints string bios function 
mov dx , 0000h ; cursor row / column zero
mov bp , vendor ; pointer to the string to output es:bp --> vendor
int 10h

ret


main:

;this function call was commented out because I am trying to get the print function to work 
;call PCI_FUNC 
;mov [vendor] , ax ; mov the result of the function into varible vendor

call PRINT_PCI
loopforever:
jmp loopforever

segment stack stack 
        resb 256 ;                              reserve 256 bytes for the stack. 
stacktop:

Re: PCI program???

Posted: Tue Nov 11, 2008 6:30 pm
by Sam111
O , sorry I found the problem
apparently I wasn't in the right segment with es:bp

must do

Code: Select all

mov ax , data
mov ds , ax
mov es , ax
That fixed it but I still don't know why
this won't do the exact same thing

Code: Select all

mov ax , ds
mov es , ax
I thought ds points to data segment apparently ds pointing to segment data is not by default?
Anybody know the reason?

Anyway I solved the problem just curious to know why?
Thought nasm by default points ds to data segment at least for -f obj?

Their are some segments they name .text instead of .code ,...etc etc
What is the differents is bss segment the same as stack? I just started coming across .rodata
Don't know what one to use so I will be carefull and always mov ax , mysegment ...etc

I thought their was only stack segment , data segment , code segment built into nasm. Any other segment is user defined? But now I am coming across bss (is this heap segment)

I am just wondering what coorospondes to what text = code bss = ??stack or heap
#-o

Re: PCI program???

Posted: Tue Nov 11, 2008 7:00 pm
by Sam111
Sorry again I got everything working except
It always prints no devices where found 'NO' means no devices

Here it is

Code: Select all


[BITS 32]

;compiled with nasm -f obj PCIdev.asm
; linked with tlink PCIdev.obj

segment data

BUS_NUMBER           db 1d               ; bus number 1 to 256 are valid values
DEVICE_NUMBER        db 3d               ;device number 1 - 32 are vaild values
FUNCTION_NUMBER      db 7d               ; function number 1-8 are vaild values
REGISTER_NUMBER      db 2d               ; register number 1-64 are vaild values
vendor               dw 0   
segment code

..start:
mov ax , data
mov ds , ax
mov es , ax
jmp main 

;PCI_FUNC is a function that returns a word from the pci configuration space
;using  data in BUS_NUMBER , DEVICE_NUMBER , FUNCTION_NUMBER , REGISTER_NUMBER 
;output is in ax
;registers effected are eax 
;Basically the function just send a 32 bit number to the configuration address and reads a word from the data address of the pci

PCI_FUNC:

push edx                            ;  saves your data that was previously in edx before using edx  
mov eax , 0                         ; initalize the register to zero
mov edx , 0                         ; initalize the register to zero

mov eax , 1                         ; mov 00000001 into  eax
shl eax , 31                        ; shift the 1 to the top most bit 10000000

mov edx , BUS_NUMBER                ; mov the bus number byte into  edx
shl edx , 16                        ;  move the bus number to bits 23 - 16

or eax , edx                        ; put bus number in eax

xor edx , edx                       ; zero out edx

mov edx , DEVICE_NUMBER             ; mov device number into edx
shl edx , 11                        ; shift the device number to bits 15-11

or eax , edx                        ; put device number in eax

xor edx , edx                       ; zero out edx

mov edx , FUNCTION_NUMBER           ; move  the function number into edx
shl edx , 8                         ; shift function number to bits  10 - 8
or eax , edx                        ; put function number in eax

xor edx , edx                       ; zero out edx

mov edx , REGISTER_NUMBER           ; move register number into edx
shl edx , 2                         ; shift register number to bits 7-2
or eax , edx                        ; put register number in eax

xor edx , edx                       ; zero out edx for the hell of it to clean it out

mov dx , 0xCF8                      ; move the configuration address for the pci into dx 
out dx , eax                        ;  send the data in eax to the configuration address port
mov dx , 0xCFC                      ; move the configuration data address into dx
in  ax , dx                         ; read a word  from the configuration data address  0xCF8

pop edx                             ; returns your previously saved edx value back to edx
 
ret 

PRINT_PCI:  ;this function prints the 2 bytes of the vendor id 

mov ax , data
mov es , ax  ; make sure es points to the same segment as data segment
mov cx , 2  ; output 2 bytes  vendor is a word
mov bx , 000Fh ; make text color attrubites ...etc white
mov ax , 1300h ; prints string bios function 
mov dx , 0000h ; cursor row / column zero
mov bp , vendor ; pointer to the string to output es:bp --> vendor
int 10h

ret


main:

call PCI_FUNC ;call pci function
cmp ax , 0FFFFh ; compare the result of pci function with ffffh no device number
je notfound   ;if a device was not found then it just puts 'NO' into the vendor varible
mov [vendor] , ax ; mov the result of the function into varible vendor
jmp print_pci
notfound:
mov word [vendor] , 'NO'
print_pci:
call PRINT_PCI
loopforever:
jmp loopforever

segment stack stack 
        resb 256 ;                              reserve 256 bytes for the stack. 
stacktop:
Does anybody see if I shifted wrong or anything in PCI_FUNC?

Code: Select all


PCI_FUNC:

push edx                            ;  saves your data that was previously in edx before using edx  
mov eax , 0                         ; initalize the register to zero
mov edx , 0                         ; initalize the register to zero

mov eax , 1                         ; mov 00000001 into  eax
shl eax , 31                        ; shift the 1 to the top most bit 10000000

mov edx , BUS_NUMBER                ; mov the bus number byte into  edx
shl edx , 16                        ;  move the bus number to bits 23 - 16

or eax , edx                        ; put bus number in eax

xor edx , edx                       ; zero out edx

mov edx , DEVICE_NUMBER             ; mov device number into edx
shl edx , 11                        ; shift the device number to bits 15-11

or eax , edx                        ; put device number in eax

xor edx , edx                       ; zero out edx

mov edx , FUNCTION_NUMBER           ; move  the function number into edx
shl edx , 8                         ; shift function number to bits  10 - 8
or eax , edx                        ; put function number in eax

xor edx , edx                       ; zero out edx

mov edx , REGISTER_NUMBER           ; move register number into edx
shl edx , 2                         ; shift register number to bits 7-2
or eax , edx                        ; put register number in eax

xor edx , edx                       ; zero out edx for the hell of it to clean it out

mov dx , 0xCF8                      ; move the configuration address for the pci into dx 
out dx , eax                        ;  send the data in eax to the configuration address port
mov dx , 0xCFC                      ; move the configuration data address into dx
in  ax , dx                         ; read a word  from the configuration data address  0xCF8

pop edx                             ; returns your previously saved edx value back to edx
 
ret 

bus number should be shifted 16 to the left right?

I have a dell dimension 4600 I looked up the chipset and it said I had a ehci controller on the pci at Device 28 function 7. I have been trying different values but everything is apparently equal to FFFFh . Can you not do in / out command's in user mode.
I am under XP using ms dos to run the program. Just prints NO

Sorry for the long post this is just been bothering me #-o

Re: PCI program???

Posted: Wed Nov 12, 2008 5:35 am
by Combuster
From what I see, you are referencing to bus_number etc as constants, not as memory operands. Hence you're trying to get pci info not on device numbers, but offsets into your file.

The C version of your code as is:

Code: Select all

  address = 0x80000000;
  offset = 0; // why
  offset = (int)(&bus) << 16; // take *address*, shift left
  address |= offset;
  offset = 0; // why
  offset = (int)(&dev) << 11; 
  address |= offset;
...
  port = 0; // why
  port = 0xCF8;
  outpurtd(port, address);  
  return inportw(0xCFC); // this is a 32-bit register

Re: PCI program???

Posted: Wed Nov 12, 2008 10:49 pm
by geppy
I am under XP using ms dos to run the program.
I'm not expert of msdos running in command prompt (right?) but wouldn't be surprised if Windows doesn't let you use in/out unless you are running on emulator or virtual machine. Windows is also free to substitute any register(port) value with something else.

Code: Select all

BUS_NUMBER           db 1           ; bus number 0 to 255 are valid values
DEVICE_NUMBER        db 3           ; device number 0 - 31 are vaild values
FUNCTION_NUMBER      db 7           ; function number 0-7 are vaild values
REGISTER_NUMBER      db 2           ; register number 0-63 are vaild values
                                    ;here you are reading revision & partial ClassCode

PCI_FUNC:
push  edx                           ; hmm, shouldn't it be 'push dx' in 16bit M$Do$
mov   eax, 80000000h                ; mov eax, (1 shl 31)

xor   edx, edx
mov   dl, byte [BUS_NUMBER]
shl   edx, 16                       ;  move the bus number to bits 23 - 16
or    eax, edx                      ; put bus number in eax

xor   edx, edx
mov   dl, [DEVICE_NUMBER]           ; mov device number into edx
shl   edx, 11                       ; shift the device number to bits 15-11
or    eax, edx                      ; put device number in eax

xor   edx, edx
mov   dl, [FUNCTION_NUMBER]         ; move  the function number into edx
shl   edx, 8                        ; shift function number to bits  10 - 8
                                    ;'mov dh, [FUNCTION_NUMBER]' is an alternative        
or    eax, edx                      ; put function number in eax

xor   edx, edx
mov   dl, [REGISTER_NUMBER]         ; move register number into edx
shl   edx, 2                        ; shift register number to bits 7-2
or    eax, edx                      ; put register number in eax

mov   dx, 0xCF8                     ; move the configuration address for the pci into dx
out   dx, eax                       ; send the data in eax to the configuration address port
mov   dx, 0xCFC                     ; move the configuration data address into dx
in    ax, dx                        ; read a word  from the configuration data address  0xCF8

pop   edx                           ; returns your previously saved edx value back to edx
ret
in my experience you are free to use lowest 2 bits of eax (part of register) on PCs on motherboards that can handle x64 CPUs but when you are reading word the REGISTER has to be 2byte aligned. And you must not read partial register.

Lowest 2bits of eax are 0 only becaouse you are supposed to read dwords.

the following is Fasm syntax but nasm& fasm are similar maybe you can convert. (Its not even worth wasting 'call' instruction for such short code)

Code: Select all

BUS          = 1           ; bus number 0 to 255 are valid values
DEVICE       = 3           ; device number 0 - 31 are vaild values
FUNCTION     = 7           ; function number 0-7 are vaild values
REGISTER     = 2           ; register number 0-63 are vaild values

PCI_FUNC:
push edx

mov   eax, 80000000h+(BUS shl 16)+(DEVICE shl 11)+(FUNCTION shl 8)+(REGISTER shl 2)
mov   dx, 0xCF8                     ; move the configuration address for the pci into dx
out   dx, eax                       ; send the data in eax to the configuration address port
mov   dx, 0xCFC                     ; move the configuration data address into dx
in    ax, dx                        ; read a word  from the configuration data address  0xCF8

pop   edx                           ; returns your previously saved edx value back to edx
ret  

Re: PCI program???

Posted: Thu Nov 13, 2008 12:17 pm
by Sam111
in my experience you are free to use lowest 2 bits of eax (part of register) on PCs on motherboards that can handle x64 CPUs but when you are reading word the REGISTER has to be 2byte aligned. And you must not read partial register.
O so , it is probably the fact that I am under an Os?

And you have to do 32 bit out commands they are not the same as two 16 bit out commands.

Interesting.

O and your right my mistake I meant

Code: Select all

[BUS_NUMBER]
should be BUS_NUMBER (i.e without the [])

Still the same result though probably need to be in boches or without an OS present to use it

Thanks