Announcement

Collapse
No announcement yet.

How do I find a PCI address?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • How do I find a PCI address?

    Hope you can help me. I have a PCI data acquisition board that we use. Currently, in the Windows - System Properties\ resources tab for this device, I manually set the I/O range to match the address I have in my application. I realize this is not the way it’s normally done, but it works so far. However, I would like to know how to read the base address of my PCI board so that I can direct my program to access it at that point instead of all this fussing around. Is there an easy way to read the address?

    P.S. I am not a great programmer, please keep that in mind.

    ------------------

  • #2
    Bill,
    the following program may do what you need. Set your I/O card's device ID at the top, %MyDeviceID=????.

    The program calls the PCI system and scans all devices it can find for a matching ID. It then looks at the config registers to see what I/O and memory are used.

    It's not perfect, but it's a start.

    Paul.
    Code:
    'pb3.5 program
    %FORCE32bit=&h66
    cls
    
    MyDeviceID%=&h8029
    MyDeviceID%=&h4750
    
    PCIpresent%=0
    LastPCIbus%=0
    PCIrev%=0
    PCImechanism%=0
    
    'get PCI system data
    !mov ax,&hb101
    !int &h1a
    
    !jnc zz
    !and ah,&hff
    !jnz xit
    
    zz:
    !db %FORCE32bit
    !cmp dx,&h20494350
    !jnz xit
    
    !mov PCImechanism%,al
    !mov PCIrev%,bx
    !mov LastPCIbus%,cl
    !mov ax,-1
    !mov PCIpresent%,ax
    
    xit:
    
    If PCIpresent% then
    
    print "last bus number = ";LastPCIbus%
    print "PCI revision number = ";hex$(PCIrev%\256);".";hex$(PCIrev% and 255)
    
    if bit(PCImechanism%,0) then print "Configuration mechanism #1 supported"
    if bit(PCImechanism%,1) then print "Configuration mechanism #2 supported"
    if bit(PCImechanism%,4) then print "Special cycle supported via configuration mechanism #1"
    if bit(PCImechanism%,5) then print "Special cycle supported via configuration mechanism #2"
    
    
    else
    print "PCI system not present"
    end if
    
    for configregister% = &h10 to &h24 step 2
    print "Register ";hex$(configregister%) ;
    
    for bus%=0 to LastPCIbus%
    for func%=0 to 255 step 8 ' 0 to 255
    flag%=0
    
    !mov ax,&hb109    ;read PCI header
    !mov bh,bus%      ;on this bus
    !mov bl,func%     ;for this device
    !mov di,configregister%   ;this config register
    
    !int &h1a
    
    !jc fail
    !and ah,&hff
    !jnz fail
    
    
    !mov addr%,cx   ;get result
    
    !inc flag%
    
    fail:
    
    if flag% and addr%<>&hffff then
    
    flag%=0
    
    !mov ax,&hb109
    !mov bh,bus%
    !mov bl,func%
    !mov di,2        ;location 2 = device ID
    
    !int &h1a
    
    !jc fail2
    !and ah,&hff
    !jnz fail2
    
    !mov config%,cx
    !inc flag%
    fail2:
    
    
    if flag% and config%=MyDeviceID% then
    
    select case (addr% and 7)
    
    case 1,3,5,7
    
    print " I/O Address used ="hex$(addr% and &hfff0)
    
    
    case 4
    print " Memory Address used(64bit) ="hex$(addr% and &hfff0)
    
    case 0,2
    print " Memory Address used(32 bit) ="hex$(addr% and &hfff0)
    
    case else
    print
    
    end select
    
    end if
    
    end if
    
    next
    next
    
    
    next
    ------------------

    Comment


    • #3
      Code:
      Macro FORCE_32_BIT = &h66
      Macro FALSE = 0
      Macro TRUE  = Not FALSE
      
      Function PbMain()
      
          Dim intDeviceID         As Integer
          Dim intPCIPresent       As Integer : intPCIPresent = 0
          Dim intLastPCIBus       As Integer : intLastPCIBus = 0
          Dim intPCIRev           As Integer : intPCIRev = 0
          Dim intPCIMechanism     As Integer : intPCIMechanism = 0
          Dim intConfigRegister   As Integer
          Dim intBus              As Integer
          Dim intFunc             As Integer
          Dim intFlag             As Integer
          Dim intAddress          As Integer
              
          
          intDeviceID = &h8029
          intDeviceID = &h4750
          
          'get PCI system data
          Asm mov ax, &hb101
          Asm int &h1a
          Asm jnc zz
          Asm and ah, &hff
          Asm jnz xit
      zz:
          Asm db  FORCE_32_BIT
          Asm cmp dx, &h20494350
          Asm jnz xit
          Asm mov intPCIMechanism, al
          Asm mov intPCIrev,bx
          Asm mov intLastPCIbus, cl
          Asm mov ax,-1
          Asm mov intPCIPresent,ax
      xit:
      
          If (intPCIPresent) Then
              StdOut "last bus number = " & Hex$(intLastPCIbus)
              StdOut "PCI revision number = " & Hex$(intPCIRev \ 256) & "." & Hex$(intPCIRev And 255)
      
              If Bit(intPCImechanism,0) Then StdOut "Configuration mechanism #1 supported"
              If Bit(intPCImechanism,1) Then StdOut "Configuration mechanism #2 supported"
              If Bit(intPCImechanism,4) Then StdOut "Special cycle supported via configuration mechanism #1"
              If Bit(intPCImechanism,5) Then StdOut "Special cycle supported via configuration mechanism #2"
          Else
              StdOut "PCI system not present"
          End If
      
          
          For intConfigRegister = &h10 To &h24 Step 2
              StdOut "Register " & Hex$(intConfigRegister) ;
      
              For intBus = 0 To intLastPCIbus
                  For intFunc = 0 To 255 Step 8 ' 0 to 255
                      
                      intFlag = FALSE
                      
                      Asm mov ax, &hb109                       ;read PCI header
                      Asm mov bh, intBus                       ;on this bus
                      Asm mov bl, intFunc                      ;for this device
                      Asm mov di, intConfigRegister            ;this config register
                      Asm int &h1a
                      Asm jc fail
                      Asm and ah,&hff
                      Asm jnz fail
      
                      Asm mov intAddress,cx                    ;get result
                      Asm inc intFlag
                  fail:
                      If (intFlag And intAddress) <> &hffff Then
                          
                          intFlag = FALSE
                          Asm mov ax,&hb109
                          Asm mov bh,intBus
                          Asm mov bl,intFunc
                          Asm mov di,2                         ;location 2 = device ID
                          Asm int &h1a
                          Asm jc fail2
                          Asm and ah,&hff
                          Asm jnz fail2
                          Asm mov intConfigRegister,cx
                          Asm inc intFlag
                  fail2:
      
                          If (intFlag And intConfigRegister) = intDeviceID Then
                              Select Case (intAddress And 7)
                                  Case 1,3,5,7
                                      StdOut " I/O Address used =" & Hex$(intAddress And &hfff0)
      
                                  Case 4
                                      StdOut " Memory Address used(64bit) = " & Hex$(intAddress And &hfff0)
                                  Case 0,2
                                      StdOut " Memory Address used(32bit) = " & Hex$(intAddress And &hfff0)
                                  Case Else
                                      StdOut
                              End Select
                          End If
                      End If
                  Next
              Next
          Next
          
          WaitKey$
          
      End Function
      ------------------

      Comment


      • #4
        Stephane,
        this is the DOS forum, the code I posted is DOS.
        Your conversion to a Windows program doesn't take this into account and will not work.

        Paul.

        Comment


        • #5
          Thanks guys,

          I was able to extract the address. Now I have another problem. I want to use the extracted address in an OUT statement but can’t seem to understand why the book says to use an integer rather than a word variable. Doesn’t the signing throw it off? Anyway, for some reason it’s not working for me. Here is a portion of code taken from what Paul Dixon sent me:

          . . .
          if flag% and config%=MyDeviceID% then

          select case (addr% and 7)
          case 1,3,5,7

          print " I/O Address used ="hex$(addr% and &hfff0)
          . . .

          With my addition added here:

          IF configregister%=&h14 then PCI_ADDRESS_OUT%=(ADDR% AND &hFFF0)

          case 4
          print " Memory Address used(64bit) ="hex$(addr% and &hfff0)

          . . .

          I use the collected address to drive a PCI board:

          OUT PCI_ADDRESS_OUT%,0 'release relays to PCI decade box
          PRINT PCI_ADDRESS_OUT%, HEX$(PCI_ADDRESS_OUT%)

          ------------
          The print statement produces this:

          -15360 C400

          this is the correct address (thanks again) but I believe the negative number is not allowing the PCI board to recognize the address. I tried using the double question mark, but then had overflow problems. Nor can I seem to use OUT &hPCI_ADDRESS_OUT%,0. How do I go about this, using a variable for a port address?

          ------------------

          Comment


          • #6
            "...where portno is an integer expression from 0 to 65535..."

            In other words, a WORD variable is fine, there. What seems to be the problem?

            ------------------
            Tom Hanlin
            PowerBASIC Staff

            Comment


            • #7
              Bill,
              the negative number is misleading, it's just the signed 16 bit representation of the &D400. Don't worry about it, you are using the variable correctly.
              OUT PCI_ADDRESS_OUT%,0 'release relays to PCI decade box


              Is the PCI card you're using an 8 bit card? Lots of them are 16 or 32 bit and will need the next byte or 3 to be set as well.
              OUT PCI_ADDRESS_OUT%,0 'release relays to PCI decade box
              OUT PCI_ADDRESS_OUT%+1,0
              OUT PCI_ADDRESS_OUT%+2,0
              OUT PCI_ADDRESS_OUT%+3,0

              Paul.

              Comment


              • #8
                I think perhaps I just don’t understand the nomenclature. On page 81 of the user's guide, it refers to an integer as having a decimal range of -32,768 to 32,767 and a WORD having a decimal range of 0 to 65,535. Since the OUT statement says nothing about negative numbers, what do I use? The % or the ??. It seems I would use the unsigned ?? word variable, but it won’t work the way I am using it. Can you help?

                ------------------

                Comment


                • #9
                  Thanks Paul, (I got your reply right after I sent my last one). The card is 16 bit I believe, and yes I do have to address
                  OUT PCI_ADDRESS_OUT%+1,0 I just took it off for clarity. So you say I am using it right. Then I'll have to try some other things. Thanks much for the help.

                  ------------------

                  Comment


                  • #10
                    Bill,
                    when using the OUT statement the sign is ignored. The 16 bits in the integer type variable you specify are treated just as bits, not a signed number.

                    What were you doing previously to output to this card when you were explicitly typing in the card's I/O address? Since the port number you get is correct the same method should still work.

                    Paul.


                    ------------------

                    Comment


                    • #11
                      Paul,

                      I got it to work now. I was barking up the wrong tree at the last there. THe board has two address locations and I got them reversed. Just assummed that I messed up the programming! Anyway I couldn't have done this without your help. Much appreciated.

                      ------------------

                      Comment


                      • #12
                        refers to an integer as having a decimal range of -32,768 to 32,767
                        and a WORD having a decimal range of 0 to 65,535
                        There are integers, and then there are INTEGERs. The INTEGER type has
                        a range of -32768 to 32767. An integer, on the other hand, may be any
                        of the integer-class types: BYTE, WORD, INTEGER, DWORD, LONG, QUAD,
                        and (sort of) POINTER.


                        ------------------
                        Tom Hanlin
                        PowerBASIC Staff

                        Comment

                        Working...
                        X