On Fri, 17 Nov 2000, Russell King wrote:

> Richard B. Johnson writes:
> > This can't be.
> 
> Richard,  before I read any further, I suggest that you get some
> documentation on a few PCI VGA cards and read up on the register
> addresses.  You may want to change your assumptions about what can and
> can't be. ;)
> 
> And I can definitely say that if you don't allow access to these "extended"
> VGA ports, BIOSes either enter infinite loops or else terminate without
> initialising the card.  Trust me; I've been successfully running various
> PCI VGA card BIOSes under an x86 emulator on an ARM machine for the past
> few months.

If a board has the capability of snooping their own special addresses,
you don't have to do anything about them. They snoop <period>.

If you look as how I showed that the resources are allocated, you
will see that it works. The I/O addresses that are used (for everything),
start at the lowest __unaliased__ address. This means that if a board
is already snooping an address, it will appear to be aliased.

The code necessary to find the lowest unaliased address looks like
this:

;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;       This initializes memory and port allocation space for PCI
;       device resource allocation.
;
ALIGN   4
INIT_PCI_RES:
        PUSH    DS                      ; Save segment
        MOV     AX,PCI_OBJ_ALLOC        ; Segment address for storage
        MOV     DS,AX                   ; Set segment
        MOV     DWORD PTR DS:[PCI_MEM],(INSTALLED_MEM SHL 14H) ; For PCI
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;       Find the lowest port address (above PCI_OFF) that doesn't have
;       any devices responding at possible aliases.
;
        MOV     EDX,0000F002H           ; Highest possible even port
FPRT:   SUB     DX,02H                  ; Keep on a WORD boundary
        IN      AX,DX                   ; See if anything there
        SLOW_IO                         ; Bus settle time for slow devices
        INC     AX                      ; 0FFFFH -> 0000H
        JNZ     SHORT PRTFND            ; We found an alias
        CMP     DX,PCI_OFF              ; Lowest port
        JNC     FPRT                    ; Continue
PRTFND: ADD     DX,02H                  ; Last good port
        MOV     DWORD PTR DS:[PCI_PRT], EDX
        POP     DS                      ; Restore segment
        RET


The code necesary to allocate resources looks like this:

;
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;       This allocates PCI-bus memory-space. Upon entry EAX contains
;       the DWORD read from the PCI-bus memory address register. This
;       can be zero (no memory to reserve). Upon exit, EAX contains
;       the value to be written back to this register, including possibly
;       zero.
;
ALIGN   4
ALLOC_PCI_ADDR:
        PUSH    EBX                             ; Save nonvolatile registers
        PUSH    DS                              ; Save segment
        PUSH    PCI_OBJ_ALLOC                   ; Where we save last result
        POP     DS                              ; DS = PCI_OBJ_ALLOC
        TEST    EAX,1                           ; IO port?
        JZ      SHORT NOTIOP                    ; Not an IO port
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;       This allocates an I/O port for the device. They are allocated on
;       16-byte boundaries even if we don't need the space.
;
        AND     EAX,(NOT 3)                     ; Mask port/reserved bits
        JZ      SHORT NOALOC                    ; No space required
        MOV     ECX,EAX                         ; Start with first address bit
        NEG     ECX                             ; ECX = length required
        CMP     ECX,000000010H                  ; At least 16 bytes?
        JNC     SHORT WAS16                     ; Yes
        MOV     ECX,000000010H                  ; At least 16 bytes
WAS16:  MOV     EBX,ECX                         ; Save allocation length
        MOV     EAX,DWORD PTR DS:[PCI_PRT]      ; Get present value
        ADD     EAX,ECX                         ; New offset value
        DEC     EAX                             ; Adjust for previous math
        NEG     ECX                             ; Create a mask
        AND     EAX,ECX                         ; N-byte boundary
        ADD     EBX,EAX                         ; EBX = for this allocation
        MOV     DWORD PTR DS:[PCI_PRT],EBX      ; Ready next
        JMP     SHORT NOALOC                    ; We are done
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;       This allocates I/O memory-space. A defect (feature) of the
;       PCI addressing scheme is that a N-byte allocation must start
;       on a N-byte boundary. This means that a 4 megabyte allocation
;       for a PCI screen-card wastes nearly 4 megabytes of address-space.
;
NOTIOP: AND     EAX,0FFFFFFF0H                  ; Clear non-address bits
        JZ      SHORT NOALOC                    ; No memory required
        MOV     ECX,EAX                         ; Start with first address bit
        NEG     ECX                             ; ECX = length required
        MOV     EBX,ECX                         ; Save allocation length
        MOV     EAX,DWORD PTR DS:[PCI_MEM]      ; Get present value
        ADD     EAX,ECX                         ; New offset value
        DEC     EAX                             ; Adjust for previous math
        NEG     ECX                             ; Create a mask
        AND     EAX,ECX                         ; N-byte boundary
        ADD     EBX,EAX                         ; EBX = for this allocation
        MOV     DWORD PTR DS:[PCI_MEM],EBX      ; Ready next
NOALOC: NEG     ECX                             ; Return with length
        POP     DS                              ; Restore segment
        POP     EBX
        RET
;
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;       This attempts to set up the PCI bus. This does  a PCI
;       snoop, finding PnP devices, allocating memory, and enabling
;       them. Note that this machine has only one bridge so we
;       don't have to check for bridges behind bridges.
;
ALIGN   4
SET_PCI:
        XOR     SI,SI                   ; Start at device zero, the bridge.
        READ_PCI SI, 0                  ; See if the bridge is there
        INC     EAX                     ; 0xffffffff becomes zero
        JNZ     SHORT BRIDGE            ; There is a bridge
        RET                             ; Forget it, no bridge
;
BRIDGE: READ_PCI  SI, PCI_CMD_STA       ; Get command/status register
        OR      AX,07H                  ; Enable I/O, Memory, Master
        WRITE_PCI SI, PCI_CMD_STA, EAX  ; Enable it.
;
        READ_PCI  SI, PCI_AMD           ; AMD Specific PCI retry count
        MOV     AL,80H                  ; Recommended value
        WRITE_PCI SI, PCI_AMD, EAX      ; Set timeout value
;
        READ_PCI  SI,PCI_LAT_CACHE      ; Latency, etc.
        MOV     AX,4008H                ; Latency / cache line size
        WRITE_PCI SI, PCI_LAT_CACHE,EAX ; Set it (if possible)
;
PCIDEV: INC     SI                      ; Ready next device
        READ_PCI SI, 0                  ; Get device ID
        INC     EAX                     ; Anybody home? 0xffffffff becomes 0
        JZ      PCINXT                  ; Nope
;
        READ_PCI  SI, PCI_CMD_STA       ; Get command/status register
        OR      AX,7                    ; Enable I/O, Memory, Bus master
        WRITE_PCI SI, PCI_CMD_STA, EAX  ; Enable it.
;
        READ_PCI  SI,PCI_LAT_CACHE      ; Latency, etc.
        MOV     AX,4008H                ; Latency / cache line size
        WRITE_PCI SI, PCI_LAT_CACHE,EAX ; Set it (if possible)
;
        MOV     DI,PCI_BASE0            ; First base address offset
PCIRES: MOV     EAX,0FFFFFFFFH          ; All bits set
        WRITE_PCI SI, DI, EAX           ; Try to set all bits
        READ_PCI  SI, DI                ; Get the results
        CALL    ALLOC_PCI_ADDR          ; Allocate resources
        WRITE_PCI SI, DI, EAX           ; Write base address (could be zero)
        INC     DI                      ; Ready next base address
        CMP     DI,PCI_CARDBUS          ; Check limits
        JC      PCIRES                  ; Next possible address
;
        READ_PCI  SI, PCI_INTER         ; Interrupt pin
        TEST    AX,0F00H                ; Isolate interrupt pin
        JZ      SHORT PCINOI            ; No interrupt required
        CALL    GET_IRQ                 ; Get IRQ value from table
PCINOI: OR      EAX,18180000H           ; Could be writable
        WRITE_PCI SI, PCI_INTER, EAX    ; Set IRQ (could be zero)
PCINXT: CMP     SI,PCI_MAX              ; End of devices?
        JC      PCIDEV                  ; Nope
        PARK_PCI                        ; Park on the bridge
        RET
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=



Cheers,
Dick Johnson

Penguin : Linux version 2.4.0 on an i686 machine (799.54 BogoMips).

"Memory is like gasoline. You use it up when you are running. Of
course you get it all back when you reboot..."; Actual explanation
obtained from the Micro$oft help desk.


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/

Reply via email to