;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                                              ;;
;; Copyright (C) 2010 KolibriOS team.     All rights reserved.  ;;
;; Distributed under terms of the GNU General Public License    ;;
;;                                                              ;;
;;                                                              ;;
;;  PCIe.INC                                                    ;;
;;                                                              ;;
;;  Extended PCI express services                               ;;
;;                                                              ;;
;;  	            art_zh  <artem@jerdev.co.uk>                ;;
;;                                                              ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

$Revision: 1463 $

;***************************************************************************
;   Function
;      pci_ext_config:
;
;   Description
;       PCIe extended (memory-mapped) config space detection
;
;   WARNINGs: 
;	1) Very Experimental! 
;	2) direct HT-detection (no ACPI or BIOS service used)
;	3) Only AMD/HT processors currently supported 
;
;***************************************************************************

PCIe_CONFIG_SPACE	equ	0xF0000000	; to be moved to const.inc
mmio_pcie_cfg_addr	dd  	0x0	; intel pcie space may be defined here
mmio_pcie_cfg_lim	dd	0x0		; upper pcie space address 


align 4

pci_ext_config:

	mov	ebx, [mmio_pcie_cfg_addr]
	or	ebx,ebx
	jz	@f
	or	ebx, 0x7FFFFFFF		; required by PCI-SIG standards 
	jnz	.pcie_failed
	add	ebx, 0x0FFFFC
	cmp	ebx, [mmio_pcie_cfg_lim]; is the space limit correct?
	ja	.pcie_failed
	jmp	.pcie_cfg_mapped
@@:
	mov	ebx, [cpu_vendor]
	cmp	ebx, dword [AMD_str]
	jne	.pcie_failed
	mov	bx, 0xC184		; dev = 24, fn = 01, reg = 84h

.check_HT_mmio:
	mov	cx, bx
	mov	ax, 0x0002		; bus = 0, 1dword to read
	call 	pci_read_reg
	mov	bx, cx
	sub	bl, 4
	and 	al, 0x80		; check the NP bit
	jz	.no_pcie_cfg
	shl	eax, 8			; bus:[27..20], dev:[19:15] 
	or	eax, 0x00007FFC		; fun:[14..12], reg:[11:2] 
	mov	[mmio_pcie_cfg_lim], eax
	mov	cl, bl
	mov	ax, 0x0002		; bus = 0, 1dword to read
	call 	pci_read_reg
	mov	bx, cx
	test	al, 0x03		; MMIO Base RW enabled?
	jz	.no_pcie_cfg
	test	al, 0x0C		; MMIO Base locked?
	jnz	.no_pcie_cfg
	xor	al, al
	shl	eax, 8
	test	eax, 0x000F0000		; MMIO Base must be bus0-aligned
	jnz	.no_pcie_cfg
	mov	[mmio_pcie_cfg_addr], eax
	add	eax, 0x000FFFFC
	sub	eax,[mmio_pcie_cfg_lim]	; MMIO must cover at least one bus
	ja	.no_pcie_cfg

;	-- it looks like a true PCIe config space; 
	mov 	eax,[mmio_pcie_cfg_addr]	; physical address
	or	eax, (PG_SHARED + PG_LARGE + PG_USER)
	mov	ebx, PCIe_CONFIG_SPACE		; linear address
	mov	ecx, ebx
	shr	ebx, 20		
	add	ebx, sys_pgdir			; PgDir entry @
@@:
	mov	dword[ebx], eax			; map 4 buses
	invlpg	[ecx]
	cmp	bl, 4
	jz	.pcie_cfg_mapped		; fix it later
	add	bl, 4				; next PgDir entry
	add	eax, 0x400000			; eax += 4M
	add	ecx, 0x400000
	jmp	@b	

.pcie_cfg_mapped:
	
;	-- glad to have the extended PCIe config field found
;	mov	esi, boot_pcie_ok
;	call	boot_log
	ret	; <<<<<<<<<<< OK >>>>>>>>>>>
	
.no_pcie_cfg:

	xor	eax, eax
	mov	[mmio_pcie_cfg_addr], eax
	mov	[mmio_pcie_cfg_lim],  eax
	add	bl, 12
	cmp	bl, 0xC0		; MMIO regs lay below this offset
	jb	.check_HT_mmio
.pcie_failed:
;	mov	esi, boot_pcie_fail
;	call	boot_log
	ret	; <<<<<<<<< FAILURE >>>>>>>>>