⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nrunpci.asm

📁 <BIOS研发技术剖析>书的源代码,包括完整的BIOS汇编语言源程序.
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	page	,132
	title .			Hooks into Run Time PCI Functions
;*****************************************************************;
;*****************************************************************;
;**                                                             **;
;**      (C)Copyright 1985-1996, American Megatrends, Inc.      **;
;**                                                             **;
;**                     All Rights Reserved.                    **;
;**                                                             **;
;**           6145-F Northbelt Pkwy, Norcross, GA 30071         **;
;**                                                             **;
;**                     Phone (770)-246-8600                    **;
;**                                                             **;
;*****************************************************************;
;*****************************************************************;

ifndef RT32
	.286
else
	.386
endif

;---------------------------------------;
	include rt.equ
	include pci.equ
	include devnode.equ
	include mac32.mac
;---------------------------------------;
	pubproc rth_pci_get_last_bus
	pubproc rth_pci_get_hw_mech
	pubproc rth_pci_special_cycle
	pubproc rth_pci_read_cfg
	pubproc rth_pci_write_cfg
	pubproc rth_pci_get_irq_reg
;---------------------------------------;
	extproc rtpci_read_cfg_byte
	extproc rtpci_write_cfg_byte
	extproc	rth_chipset_route_pci_irq
;---------------------------------------;
CFG_SPACE_INDEX_REG	equ	0CF8h	;For systems with config mechanism 1
CFG_SPACE_DATA_REG	equ	0CFCh
;---------------------------------------;
;	C O D E     S E G M E N T	;
;---------------------------------------;
ifndef RT32
	cgroup	group	_text
	_text segment word public 'CODE'
		 assume	cs:CGROUP
	.386
else
	.386
	cgroup	group	_runtime32
	_runtime32 segment word public USE32 'CODE'
		 assume	cs:cgroup
endif


ifndef RT32
	include	setupequ.ext
;------------------------------------------------------------------------------;
;                                                                              ;
;                              16 Bit Code only                                ;
;                                                                              ;
;------------------------------------------------------------------------------;

;---------------------------------------;
; rth_pci_get_irq_priority_map          ;
;---------------------------------------;--------------------------------------;
; This function returns an ordered list of all possible IRQ levels             ;
; that may be routed to the given PCI bus#/device#.  If some IRQ levels have   ;
; already been routed to the PCI bus, then the list may be affected.  The      ;
; function dih_pci_route_irq (see below) must be able to route any of the IRQ  ;
; levels in the list to the given bus#/device# without affecting previous IRQ  ;
; routing.  This function should return a prioritized list of IRQ levels for   ;
; the given bus#/device#.  The list should be written into the caller's buffer ;
; (at DS:SI) and should be terminated with a zero byte.  The list should       ;
; contain one byte for each IRQ level that can be routed to the slot.          ;
;                                                                              ;
; NOTE: This function is called only during POST (in real mode).               ;
;                                                                              ;
; Input: BL = Device/Function number to route IRQ to                           ;
;                Bits 7-3: PCI device number                                   ;
;                Bits 2-0: Function number within the device                   ;
;        BH = Bus number to route IRQ to                                       ;
;        DL = PCI Int pin that the device uses                                 ;
;             (01=IntA, 02=IntB, 03=IntC, 04=IntD).                            ;
;        DS:SI = buffer to hold list of routable IRQ levels (17 bytes max)     ;
;                                                                              ;
; Output: List of IRQ levels in caller's buffer (DS:SI)                        ;
;                                                                              ;
; Destroys: Nothing                                                            ;
;------------------------------------------------------------------------------;
	extrn	rth_check_reg_for_irq:near
	public	irq_map
	public	rth_pci_get_irq_priority_map

rth_pci_get_irq_priority_map	proc near
	pusha

	push	ds
	push	cs
	pop	ds
	push	dx
	call	rth_pci_get_irq_reg	;Returns AL=chip reg, DX=IRQ bit map
	mov	di, dx			;Save IRQ bit map in DI
	pop	dx
	pop	ds
	jc	get_map_done		;Br if unknown device

	or	al, al
	jz	get_map_done		;Br if Device/Int Pin is not connected
	cmp	al, 0F0h
	jae	get_map_not_routed_yet	;Br if Device/Int Pin is hardwired

;----------------- Chipset dependant code starts here ------------------------

;  Check to see if this chipset reg has already been programmmed to route an
;  IRQ.  If it has, then just put that one IRQ into the caller's buffer (at
;  DS:SI), inc SI, then jump to get_map_done.  AL contains chipset register
;  from the IRQ Routing Table above.  DI must be preserved through this code.

	call	rth_check_reg_for_irq	; AL = 00 IRQ not routed yet
					;    <>00 already routed IRQ
	or	al,al			; IRQ routed already ?
	jz	not_routed_yet
;  IRQ already routed..
	mov	byte ptr [si], al	;Put byte into caller's buffer
	inc	si
	jmp	short get_map_done
not_routed_yet:
;----------------- Chipset dependant code ends here ---------------------------

	;This chipset reg has not been used to route an IRQ yet.  DX contains
	;a bit map of IRQs that can be routed to the given Device/Int Pin.
	;Scan through the irq_map list below and copy into the caller's buffer
	;any IRQ levels that have a bit set in DX.

get_map_not_routed_yet:
;  BH, BL = bus#, dev#, func#, DL = 1/2/3/4 for INTA/B/C/D
	call	manual_irq_selection	; check IRQ selection and if selected
					; put the IRQ in buffer and INC SI
	mov	bx, offset cgroup:irq_map
get_map_copy_table:
	movzx	ax, byte ptr cs:[bx]	;Get next byte from table
	bt	di, ax			;Copy bit number AX of BX into CF
	jnc	get_map_skip_bit	;Br if bit not set in DX
	mov	byte ptr [si], al	;Put byte into caller's buffer
	inc	si
get_map_skip_bit:
	inc	bx
	or	al, al
	jnz	get_map_copy_table	;Repeat the copy loop until 0 found

get_map_done:
	mov	byte ptr [si], 0	;Put a zero to mark end of buffer
	popa
	ret
rth_pci_get_irq_priority_map	endp

;irq_map		db	11, 10, 9, 12, 5, 3, 7, 4, 15, 14, 0
;irq_map		db	11, 10, 9, 15, 5, 3, 7, 4, 14, 0
irq_map         db      10, 11, 12, 9, 5, 15, 14, 0, 0, 0, 0, 0
;------------------------------------------------------------------------------;
manual_irq_selection:
;  BH, BL, DL
;  DS:SI = ptr to buffer
;  register destroyed : AL BX CX SI
	push	di
	and	bl,0f8h			; discard func#
	xchg	bl,bh
	movzx	cx, byte ptr cs:rth_pci_device_count
	mov	di, offset cs:rth_pci_irq_routing_table
mis_02:
	cmp	bx, word ptr ((pci_irq_entry ptr cs:[di]).pirq_bus_number)
	je	mis_01			;Br if found bus,dev
	add	di, size pci_irq_entry	;DI points to next entry in table
	loop	mis_02
	jmp	short mis_00		; not found
mis_01:
	mov	al,(pci_irq_entry ptr cs:[di]).pirq_phys_slot; phy slot#
	dec	al			; slot# can not be zero
	cmp	al,(offset cgroup:xlat_slot_setupq_table_end-offset cgroup:xlat_slot_setupq_table)
	jae	mis_00			; slot# invalid
	mov	bx,offset cgroup:xlat_slot_setupq_table
	xlat	cgroup:xlat_slot_setupq_table; AL = setup question#
	db	9ah			; CALL FAR F000:EED5 (CHECK_CMOS_DATA)
	dw	0eed5h
	dw	0f000h
	jz	mis_00			; AUTO
	mov	ds:byte ptr [si],al
	inc	si
mis_00:
	pop	di
	ret
xlat_slot_setupq_table		label	byte
	db	q_pci_slot1_irq
	db	q_pci_slot2_irq
	db	q_pci_slot3_irq
	db	q_pci_slot4_irq
xlat_slot_setupq_table_end	label	byte
;------------------------------------------------------------------------------;
endif

;------------------------------------------------------------------------------;
;                                                                              ;
;                              16/32 Bit Code                                  ;
;                                                                              ;
;------------------------------------------------------------------------------;

;---------------------------------------;
; rth_pci_route_irq                     ;
;---------------------------------------;--------------------------------------;
; This function is to physically route an IRQ to a PCI bus#/device#.           ;
; The IRQ level that must be routed should be one from the list that was       ;
; returned by dih_pci_get_irq_priority_map (see above).                        ;
;                                                                              ;
; NOTE: This function is assembled twice, once for real mode code, and once    ;
;       for 32 bit protected mode code.  All calls must be made using the      ;
;       callproc macro.  Do not modify and segment registers.                  ;
;                                                                              ;
; Input: AL = IRQ level to route to the PCI device                             ;
;        BL = Device/Function number to route IRQ to                           ;
;                Bits 7-3: PCI device number                                   ;
;                Bits 2-0: Function number within the device                   ;
;        BH = Bus number to route IRQ to                                       ;
;        DL = PCI Int pin that the device uses                                 ;
;             (01=IntA, 02=IntB, 03=IntC, 04=IntD).                            ;
;        DS = F000 (or selector pointing to F000 if called in 16-bit protected ;
;             mode).  If called in 32-bit protected mode the DS selector will  ;
;             be set to the same base as the CS selector and will not          ;
;             necessarily be F0000 (some software calls with DS = CS = 0 base) ;
;             This means that in the 32-bit code, no offset in CS should be    ;
;             accessed directly.  You must first get the value of EIP by       ;
;             making a call from a known offset and popping the return         ;
;             address, and then subtracting the offset of that address from    ;
;             the popped value.  The resulting value must be added to any      ;
;             CS:offset before that label is accessed.                         ;
;                                                                              ;
; Output: CF = Set if error, clear if successful                               ;
;                                                                              ;
; Destroys: Nothing                                                            ;
;------------------------------------------------------------------------------;
defproc rth_pci_route_irq
	pusha

	mov	ah, al			;Save IRQ level in AH
	callproc rth_pci_get_irq_reg	;Returns AL=chip reg, DX=IRQ bit map
	jc	route_irq_done		;Br if unknown device

	or	al, al
	stc				;Set CF in case this jz jumps
	jz	route_irq_done		;Br if Device/Int Pin is not connected
	cmp	al, 0F0h
	jae	route_irq_success	;Br if Device/Int Pin is hardwired

;----------------- Chipset dependant code starts here ------------------------

;  Program the chipset register in AL with the IRQ level in AH.
;  Also make sure this IRQ is set to level (or edge if needed) trigger.

	callproc rth_chipset_route_pci_irq; route IRQ

;----------------- Chipset dependant code ends here ---------------------------

route_irq_success:
	clc				;Indicate success
route_irq_done:
	popa
	ret
endproc rth_pci_route_irq


;---------------------------------------;
; rth_pci_get_irq_reg                   ;
;---------------------------------------;--------------------------------------;
; This function returns the chipset IRQ register that should be programmed in  ;
; order to route an IRQ to a given PCI device number / Int Pin number.  It     ;
; also returns a bitmap of IRQs that may be routed to the given Device/Int Pin.;
; This information is extracted from the PCI IRQ Routing Table above.          ;
;                                                                              ;
; NOTE: This function does not need to be modified for most platforms.         ;
;                                                                              ;
; NOTE: This function is assembled twice, once for real mode code, and once    ;
;       for 32 bit protected mode code.  All calls must be made using the      ;
;       callproc macro.  Do not modify and segment registers.                  ;
;                                                                              ;
; Input: BL = Device/Function number to route IRQ to                           ;
;                Bits 7-3: PCI device number                                   ;
;                Bits 2-0: Function number within the device                   ;
;        BH = Bus number to route IRQ to                                       ;
;        DL = PCI Int pin that the device uses                                 ;
;             (01=IntA, 02=IntB, 03=IntC, 04=IntD).                            ;
;        DS = F000 (or selector pointing to F000 if called in 16-bit protected ;
;             mode).  If called in 32-bit protected mode the DS selector will  ;
;             be set to the same base as the CS selector and will not          ;
;             necessarily be F0000 (some software calls with DS = CS = 0 base) ;
;             This means that in the 32-bit code, no offset in CS should be    ;
;             accessed directly.  You must first get the value of EIP by       ;
;             making a call from a known offset and popping the return         ;
;             address, and then subtracting the offset of that address from    ;
;             the popped value.  The resulting value must be added to any      ;
;             CS:offset before that label is accessed.                         ;
;                                                                              ;
; Output: CF = Set if error, clear if successful                               ;
;         AL = Chipset IRQ register number from rth_pci_irq_routing_table      ;
;              in the file RTH-PCI.ASM                                         ;
;         DX = Bitmap of IRQs that can be routed to the given Device/Int Pin.  ;
;                Bit 0: If set, chipset can route IRQ 0 to the device/pin      ;
;                ...     ...                                                   ;
;                Bit 15: If set, chipset can route IRQ 15 to the device/pin    ;
;                                                                              ;
; Destroys: Nothing                                                            ;
;------------------------------------------------------------------------------;
defproc rth_pci_get_irq_reg
	assume	ds:cgroup
	push	ebx
	push	ecx
	push	esi

ifndef RT32

	extrn	rth_pci_device_count:byte
	extrn	rth_pci_irq_routing_table:byte
	movzx	cx, byte ptr ds:rth_pci_device_count
	mov	esi, offset ds:rth_pci_irq_routing_table

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -