;	[]==========================================================[]
;
;	    This source code is classified as confidential and
;	    contains trade secrets owned by Award Software, Inc.
;
;	    		Copyright (c) 1984, 1996
;			Award Software, Inc.
;			All rights reserved.
;
; 	[]==========================================================[]

;----------------------------------------------------------------------------
;Rev  	Date	 Name	Description
;----------------------------------------------------------------------------
;R12	04/02/99 RCH	Fixed complier error if the MP platform do not support
;			INTIN16-23 (for VIA/596B IOAPIC).
;
;R11	01/08/99 RCH	Added PCI routing thru INTIN20 to INTIN23 of IOAPIC
;			for MP platform.
;R10	11/16/98 KVN	Set CPU 2 entry data to dynamic build for MP table.We
;			always build 2 processor entry data in MP table of the
;			past. That will cause 'Solaris for x86 boot system'
;			hang up. Now we only build 1 processor entry into MP
;			table when system only 1 CPU.
;R09	09/23/98 RCH	Fixed wrong MP table v1.4 report while PCI devices 
;			share same IRQ.
;R08	08/14/98 RCH	Fixed 15-16MB memory hole not working if P6 or P II
;			CPU is used and L1/L2 cache is enabled
;R02A	01/17/98 KVN	Set CPU2 init flag data segment to correctly
;R07	06/12/97 RCH	Fixed the L2 cache of second Penitum II CPU always
;			be disabled.
;R06A	06/03/97 RCH	R06 is not enough for MPS v1.1,More fix for SCO/UNIX
;			SMP version.
;R06	05/27/97 RCH	Added MPS version 1.1/1.4 control for different
;			SMP Operating System
;R03A	05/26/97 RCH	Fixed BIOS can not display L2 cache size of second
;			Pentium Pro.
;R05	05/21/97 RCH	Added recording P6 update ID for Intel's P6 utility
;R04	05/21/97 RCH	Don't send SMI to second CPU if second CPU is absent
;			to prevent noise on local APIC bus
;R03	05/21/97 RCH	Fixed BIOS can not display L2 cache size of secondary
;			Klamath CPU in MP system
;R02	05/20/97 KVN	Fix system hang on issue SMI during NT multi processor
;			booting and physical processor are 2
;R01	05/03/97 KVN	Fix MASM compiler error if define "MP_TBL_SELECTABLE"
;			in BIOS.CFg

.XLIST
		INCLUDE BIOS.CFG

		INCLUDE COMMON.EQU
		INCLUDE POST.EQU
		INCLUDE	CPU.EQU

		INCLUDE	COMMON.MAC
		INCLUDE	POST.MAC

;Macro for far calling from E-segment and the called routine is in F-segment
F000_call	MACRO	func_addr
		LOCAL	Ret_addr
		push	0e000h
		push	offset cs:Ret_addr
		push	offset F000_func_end
if ((.TYPE func_addr) and 10h)			;func_addr is register?
		push	func_addr		;Yes,direct push
else
		push	offset func_addr
endif
		FAR_JMP <OFFSET F000_VECT>,0F000H
Ret_addr:
		ENDM

ifdef	MP_SUPPORT
		extrn	PCI_SLOT_CFG:near	;R09
		extrn	IrqRout_Table:near	;R09

		extrn	ExtCache_Item:near	;R07
		extrn	P1_Upd_Ver:near		;R05
		extrn	P2_Upd_Ver:near		;R05
		extrn	F000_func_end:Near
		extrn	F000_VECT:Near
		extrn	F000_call_proc:near
		extrn	F000_Shadow_W:near
		extrn	F000_Shadow_R:near
		extrn	cpu_halt:near			
		extrn	E000_Enter_Prot_Mode:near
		extrn	E000_Back_Real_Mode:near
ifdef	P6_BIOS_ONLY
		extrn	Init_Mtrr:near
		extrn	Ct_MemHole_Status:near	;R08
endif	;P6_BIOS_ONLY
		extrn	Cpu_Apic_Init:near
		extrn	P1_SiGn:near
		extrn	P2_SiGn:near
 		extrn	MP_FP_Stru:near				
 		extrn	MP_FP_CHKSUM:ABS			
 		extrn	MP_FP_LENGTH:ABS			
 		extrn	MP_FP_Stru:near				
		extrn	AGet_CfgSpace_Word:near
		extrn	AGet_CfgSpace_Byte:near
		extrn	Get_Ct:near
		extrn	NCR_810_FOUND:ABS
		extrn	Get_Max_PciBus:near
;R01 start
;R06 ifdef	MP_TBL_SELECTABLE
		extrn	If_MP_PLUGGED:near
		extrn	MP_Tbl_Item:near
		extrn	F000_GetItem_Value:near
;R06 endif	;MP_TBL_SELECTABLE
;R01 end
endif;	MP_SUPPORT

.LIST
.386p
		PAGE	60,132
		TITLE	MPINIT - Initial codes for MP system

EGROUP		GROUP	ECODE
ECODE		SEGMENT USE16 PARA PUBLIC 'ECODE'
		ASSUME	CS:EGROUP,DS:EGROUP

                public  Init_APIC
Init_Apic	proc	near
ifdef	MP_SUPPORT

ifdef	P6_BIOS_ONLY
;Code for P6
                push    ds
                push    es
                push    esi

                xor     ax, ax
                mov     ds, ax
                mov     ds:byte ptr [500H], 0	;assume no 2nd CPU plugged
                mov     ds:byte ptr [501H], Vacant

;R07 - start
	;set L2 cache's CMOS setting in temporary area 
		mov	si,offset ExtCache_Item	;get CMOS status
		call	F000_GetItem_Value
		mov	ds:byte ptr [502h],al	;save L2 CMOS setting
;R07 - end

;R08 - start
	;set 16-16MB memory hole status in temporary area 
		F000_CALL Ct_MemHole_Status	;get memory status
		mov	ds:byte ptr [503h],al	;save 15-16MB memory hole
;R08 - end


;Check if IO APIC exist or not, if not , disable P6 local APIC and
;skip initialization
		call	E000_Enter_Prot_Mode	;enter CPU protected mode
		mov	esi,0FEC00000H		;I/O APIC address
		xor	eax,eax			;test pattern
		mov	[esi],eax  	 	;write APIC reg. addr.
		mov	ecx,[esi]   		;Read APIC reg. addr.
		cmp	al,cl		      	;I/O APIC existed ?
		pushf
		call	E000_Back_Real_Mode	;return to real mode
		popf
		je	short IO_Apic_Exist

;disable local APIC if not support MP
		mov	ecx,27			;MSR index 27
		RDMSR
		and	ah,NOT 08H		;disable CPU APIC
		WRMSR

		jmp	No_IO_Apic		

IO_Apic_Exist:

		F000_CALL Cpu_Apic_Init

		call	E000_Enter_Prot_Mode	;enter CPU protected mode

		call	Init_IO_Apic		;initial IO APIC


		;**** Set I/O APIC ID
		mov	esi, 0fec00000h
		mov	eax, ds:dword ptr [esi]
		xor	al,al				; set index 0 
		mov	ds:dword ptr [esi], eax		; index

		mov	eax, ds:dword ptr [esi+10h]
		and	eax, 0f0ffffffh
		or	eax, 002000000h			; set ID to 2
		mov	ds:dword ptr [esi+10h], eax	; index

		;set Local APIC ID to 0 for BSP CPU
		mov	esi,0fee00020h			;local APIC ID 
		xor	eax,eax	 			;set ID to 0
		mov	[esi],eax


		;*** Send Startup IPI to Detect if CPU2 Present
		mov	esi, 000e0000h
		mov	si, offset CPU2_Init
		mov	cx, CPU2_Init_Len
		mov	edi, CPU2_SEGMENT shl 4
	@@:
		mov	al, ds:byte ptr [esi]
		mov	ds:byte ptr [edi], al
		inc	di
		inc	si
		loop	short @B

		mov	byte ptr ds:[5ffh],5ah		;R02 Set CPU2 init end Flag

		;*** Clear ESR first
		mov	esi, 0fee00280h			; ESR
		xor	eax, eax
		mov	ds:dword ptr [esi], eax
		mov	eax, ds:dword ptr [esi]

		;*** issue start-up command to detect 2nd CPU
		mov	si, 0300h			; ICR Low
		mov	eax, ds:dword ptr [esi]
		and	eax, 0ffff3800h
		or	eax, 0000CC600h	+ (CPU2_SEGMENT shr 8)
		mov	[esi], eax

		;*** wait 2nd CPU to execute
		mov	cx, 1000h
	@@:
		NEWIODELAY
		loop	short @B

	NANANA:						;R02
		cmp	byte ptr ds:[5ffh],5ah		;R02 Wait CPU2 Init
		jne	short NANANA			;R02

;record CPU APIC ID and version and save it in MP table
		mov	eax,dword ptr ds:[0fee00020h]	;local APIC ID in BL
		shr	eax,24
		and	al,0fH				;legal value 0..F
		mov	bl,al

		mov	eax,dword ptr ds:[0fee00030h]	;local APIC version in BH
		mov	bh,al

		call	E000_Back_Real_Mode	;return to real mode

;First - Force system BIOS readable and shadow RAM writeable
		push	bx			;save APIC ID	
		F000_CALL 	F000_Shadow_W

		push	0f000h
		pop	ds

		;Read CPU ID and save in MP table
		mov	eax,1			;eax = 1 to read CPU ID
		db	0fh,0A2h		;CPU ID instruction

		mov	si,offset P1_SiGn
		mov	dword ptr ds:[si],eax 	;save CPU signature for CPU 1
		mov	si,offset P2_SiGn
		mov	dword ptr ds:[si],eax 	;save CPU signature for CPU 1

		xor	ax,ax
		mov	es,ax			;temporary segment
                cmp     byte ptr es:[500H],0AAH ;2 CPUs plugged
		jne	short No_2ndCpu		

		mov	eax,dword ptr es:[0504H]	;get 2nd CPUID
		mov	dword ptr ds:[si],eax 	;save CPU signature for CPU 2

;R05 - starts
	;save 2nd CPU's update version
		mov	al, byte ptr es:[0508H]
		mov	si,offset P2_Upd_Ver
		mov	byte ptr ds:[si], al
;R05 - ends

No_2ndCpu:

;R05 - starts
	;save 1st CPU's update version
		mov	si, 508h
		call	Read_P6_Update_Version
		mov	al, es:[si]
		mov	si,offset P1_Upd_Ver
		mov	byte ptr ds:[si], al
;R05 - ends

		pop	bx			;restore APIC ID

;Last - Force system BIOS shadow RAM readonly
		F000_CALL F000_Shadow_R

		call	Temp_SMBase_For_2nd_CPU		

No_IO_Apic:						

                pop     esi
                pop     es
                pop     ds
else;	P6_BIOS_ONLY
;Code for P5

                push    ds
                push    es
                push    esi

		F000_CALL Cpu_Apic_Init

		call	E000_Enter_Prot_Mode	;enter CPU protected mode

		call	Init_IO_Apic		;initial IO APIC

		;**** Set I/O APIC ID
		mov	esi, 0fec00000h
		mov	eax, ds:dword ptr [esi]
		mov	al, 00h
		mov	ds:dword ptr [esi], eax		; index

		mov	eax, ds:dword ptr [esi+10h]
		and	eax, 0f0ffffffh
		or	eax, 002000000h			; set ID to 2
		mov	ds:dword ptr [esi+10h], eax	; index


		;*** Set ICR High
		mov	esi, 0fee00310h			; ICR High
		mov	eax, ds:dword ptr [esi]
		and	eax, 0f0ffffffh
		or	eax, 001000000h			; ID
		mov	[esi], eax
		;*** Set ICR Low
		mov	si, 0300h			; ICR Low
		mov	eax, ds:dword ptr [esi]
		and	eax, 0fffff8ffh
		or	ax, 0c500h			; Assert Init
		mov	[esi], eax
		mov	cx, 1000h
	@@:
		NEWIODELAY
		loop	short @B


		;*** Send Startup IPI to Detect if CPU2 Present
		mov	esi, 000e0000h
		mov	si, offset CPU2_Init
		mov	cx, CPU2_Init_Len
		mov	edi, CPU2_SEGMENT shl 4
	@@:
		mov	al, ds:byte ptr [esi]
		mov	ds:byte ptr [edi], al
		inc	di
		inc	si
		loop	short @B

		mov	cx, 10
Startup_IPI_Loop:
		push	cx
		;*** Clear ESR first
		mov	esi, 0fee00280h			; ESR
		xor	eax, eax
		mov	ds:dword ptr [esi], eax
		mov	eax, ds:dword ptr [esi]

		;*** Set ICR High
		mov	si, 0310h			; ICR High
		mov	eax, ds:dword ptr [esi]
		and	eax, 0f0ffffffh
		or	eax, 001000000h
		mov	[esi], eax
		;*** Set ICR Low
		mov	si, 0300h			; ICR Low
		mov	eax, ds:dword ptr [esi]
		and	eax, 0ffff3800h
		or	ax, 0600h + (CPU2_SEGMENT shr 8)
		mov	[esi], eax
		;*** Loop for Some Time
		mov	cx, 1000h
	@@:
		NEWIODELAY
		loop	short @B
		pop	cx
		loop	short Startup_IPI_Loop

		call	E000_Back_Real_Mode	;return to real mode

		call	Temp_SMBase_For_2nd_CPU	

                pop     esi
                pop     es
                pop     ds
endif;	P6_BIOS_ONLY

endif;	MP_SUPPORT
                ret
Init_Apic	endp

ifdef	MP_SUPPORT

;Function : Initaial IO APIC to reset value
;Input    : none
;Output   : none
Init_IO_Apic	proc	near
;Initial I/O APIC , otherwise SCO/UNIX can not recognize second CPU
;when system shutdown and reboot
IO_APIC_unit	EQU	0fec00000h
		mov	esi,IO_APIC_unit
		mov	edi,10h
		xor	ebx,ebx
IO_init_loop:
		mov	edx,1
		mov	[esi],edx
		mov	[esi+10h],ebx
		mov	[esi],edx
		mov	ecx,[esi+10h]
		mov	[esi],edx
		mov	eax,0ffffffffh
		mov	[esi+10h],eax
		mov	dword ptr [esi],edx
		mov	eax,[esi+10h]
		and	eax,0ff0000h
		and	ecx,0ff0000h
		cmp	eax,ecx
		jne	short Next_IO_Addr
		shr	eax,10h
		cmp	ax,0efh
		jg	short Next_IO_Addr
		shr	ecx,10h
		cmp	cx,0efh
		jg	short Next_IO_Addr
		mov	ecx,78h
		mov	[esi],ebx
		mov	[esi+10h],ebx
		mov	eax,0fh
		mov	edx,10000h
@@:
		inc	eax
		mov	[esi],eax
		mov	[esi+10h],edx
		inc	eax
		mov	[esi],eax
		mov	[esi+10h],ebx
		loop	short @B
  
		mov	dword ptr [esi],ebx
Next_IO_Addr:
		add	esi,1000h
		dec	edi
		jnz	IO_init_loop
		ret
Init_IO_Apic	endp

;[]==============================================================[]
;
; Cpu2_Init:
;
;       Detect second CPU and initial APIC
;
;Saves: 
;       
;       All except ax,dx,es,ds,flag
;Input : None
;Output: None
;
;[Notes]
;
;[]==============================================================[]

CPU2_Init	proc	near
ifdef	P6_BIOS_ONLY
;Code for P6
		cli
NotVacant       EQU     0ffh
Vacant          EQU     00h

;R02A		mov	byte ptr ds:[5ffh],-1		;R02 clear CPU2 init end Flag
                mov     al, NotVacant
                xor     bx,bx
                mov     es,bx
		mov	byte ptr es:[5ffh],-1		;R02A clear CPU2 init end Flag

TestLock:
                xchg    byte ptr es:[0501H],al          ;Lock semaphore
                cmp     al,NotVacant                    ;Someone in critical section?
                jz      short TestLock                  ;Yes, check semaphore again

;                add     byte ptr es:[0500H],1          ;CPU count increment
                mov     byte ptr es:[500H],0AAH         ;Kludge! work for dual processors only
ReleaseLock:
                mov     al,Vacant                       ;Release the lock
                xchg    byte ptr es:[0501H],al          ;Release the lock

;R03Aifdef	KLAMATH_CPU_ONLY					;R03
;R03A	;save L2 cache size in routine Init_Mtrr(cpupost.asm)	;R03
;R03A		mov	eax,2			;read cache isze
;R03A		db	0Fh,0A2h		;OP code: CPUID
;R03A		mov	es:[0502H],dl		;save L2 cache size
;R03Aendif;	KLAMATH_CPU_ONLY					;R03

		mov	eax,1			;read CPUID
		db	0Fh,0A2h		;OP code: CPUID
		mov	es:[0504H],eax		;save 2nd's CPUID

	;set up stack for far call operation
		mov	ax,cs
		mov	ss,ax
		mov	sp,2000H

	;Set MTRR register for second CPU
		FAR_CALL <Init_Mtrr>,0E000H		;set MTRR registers

;R03A - start
	;save L2 cache size in temporary area
		mov	eax,2			;read cache isze
		db	0Fh,0A2h		;OP code: CPUID
		xor	ax,ax
		mov	es,ax			;segment 0
		mov	es:[0502H],dl		;save L2 cache size
;R03A - end


;R05 - starts
		mov	si, 508h
		call	Read_P6_Update_Version
;R05 - ends

		FAR_JMP	<offset Set_2nd_Local_APIC_ID>, 0E000h
;R05 - start
Read_P6_Update_Version	Proc	Near

		pushad

		mov	ecx, 8Bh
		xor	eax, eax
		xor	edx, edx
		WRMSR

		mov	eax, 1
		db	0Fh, 0A2h

		mov	ecx, 8Bh
		RDMSR

		mov	es:[si], dl		;save 2nd CPUID version

		popad
		ret

Read_P6_Update_Version	Endp
;R05 - end

else;	P6_BIOS_ONLY
;Code for P5
		cli
		xor	ax,ax
		mov	es,ax
		mov	byte ptr es:[0500H],0AAH	;set CPU detected
		far_jmp	<offset cpu_halt>, 0F000h
endif;	P6_BIOS_ONLY
CPU2_Init_Len	EQU	$-offset CPU2_Init
CPU2_Init	endp

;Function : Deliver a SMI to 2nd CPU for changing SMBASE to avoid SMBASE
;	    conflict with 1st CPU while changing 1st CPU's SMBase by issue
;	    software SMI by chipset.
;Note     : This routine should invoked before 1st CPU's SMI be initiated
;Input   : none
;Output  : none
		Public	Temp_SMBase_For_2nd_CPU
Temp_SMBase_For_2nd_CPU	Proc	Near


;R04 - starts
	;Don't send SMI to second CPU if the second CPU is not present
	;to prevent endless noise on local APIC bus
		call	If_MP_PLUGGED
		jnc	short @F
		ret
	@@:
;R04 - ends

	;Copy change SMBASE code into original SMBASE 3800:0 for SMBase
	;changing.
		mov	ax,cs
		mov	ds,ax			; source address
		mov	ax,03800h		; orginal CPU SMBase
		mov	es,ax			; destination address
		mov	cx,8000h
		mov	si,offset @F		; code for change SMBASE
		xor	di,di
		cld
		rep	movsb

		call	E000_Enter_Prot_Mode	;enter CPU protected mode

	;Deliver a SMI to 2nd CPU to change SMBASE by local APIC
		mov	esi, 0FEE00300h		; command register
		mov	eax, 0000C0200h		; issue SMI
		mov	[esi], eax

		call	E000_Back_Real_Mode	;return to real mode

		ret

	@@:
		mov	eax, (CPU2_SEGMENT shl 4)
		mov     di,0FEF8h		; SMBASE register
		mov     dword ptr cs:[di], eax
		db	0Fh, 0AAh		;RSM

Temp_SMBase_For_2nd_CPU	Endp

ifdef	P6_BIOS_ONLY				
Set_2nd_Local_APIC_ID:
	call	E000_Enter_Prot_Mode	;enter CPU protected mode
	mov	dword ptr ds:[0fee00020h], 01000000h ;local APIC ID = 1
	call	E000_Back_Real_Mode	;return to real mode
	xor     ax,ax			;R02
	mov     es,ax			;R02
	mov	byte ptr es:[5ffh],5ah	;R02 Set Init End Flag
	far_jmp	<offset cpu_halt>, 0F000h
endif	;P6_BIOS_ONLY				

;[]==============================================================[]
;
; MP_Final_Init:
;
;       Build dynamic MP table and re-make checksum for MP table
;
;Saves: 
;       
;Input : None
;Output: None
;
;[]==============================================================[]
		public	MP_Final_Init	
MP_Final_Init	proc	near

;R06 ifdef	MP_TBL_SELECTABLE
;R06 
;R06 		call	If_MP_PLUGGED	   	;single CPU plugged ?
;R06 		jnc	short Not_OneCpu	;no, more than one
;R06 
;R06 		mov	si,offset MP_Tbl_Item
;R06 		call	F000_GetItem_Value
;R06 		or	al,al			;MP enabled ?
;R06 		jz	short Mp_Disabled
;R06 endif;	MP_TBL_SELECTABLE

Not_OneCpu: 

	
		call	CheckSum_Mp_Table

Mp_Disabled:

		ret
MP_Final_Init	endp

;Function : Modify checksum of MP table
;Input    : none
;Output   : None 
CheckSum_Mp_Table	proc	near
;Build MP table and re-calculate checksum
;Second - calculate checksum of MP Floating Pointer structure
		push	0f000H
		pop	ds			;DS point to FP structure

;First - Force system BIOS readable and shadow RAM writeable
		F000_CALL F000_Shadow_W

		call	Build_MpTable		;build dynamic MP table

		mov	si,offset MP_FP_Stru	;checksum stating location
		mov	cx,MP_FP_LENGTH		;length to check sum
		xor	bl,bl			;initial checksum
		cld
Check_Sum1:
		lodsb
		add	bl,al
		loop	short Check_Sum1		

		neg	bl			;checksum byte
		mov	si,offset MP_FP_Stru
		mov	[si+MP_FP_CHKSUM],bl

;Third - calculate checksum of MP Configuration Table
		mov	si,MP_ShadowTbl_Address	;checksum stating location
		mov	cx,[si+4]		;length to check sum
		xor	bl,bl			;initial checksum
		cld
Check_Sum2:
		lodsb
		add	bl,al
		loop	short Check_Sum2

		neg	bl			;checksum byte

		mov	si,MP_ShadowTbl_Address
		mov	[si+MP_CFG_CHKSUM],bl

;Last - Force system BIOS shadow RAM readonly
		F000_CALL 	F000_Shadow_R

		ret
CheckSum_Mp_Table	endp

ENTRY_LEN	EQU	8
;Function : Build dynamic PCI/IRQ MP table 
;Input    : DS = F000H and shadow Read/Writeable
;Output   : none
Build_MpTable	proc	near

		pushad
		push	ds
		pop	es		;ES=F000H

		push	ds

		push	cs
		pop	ds		;DS=E000H

	;copy MP_config_Table to shadow buffer
		mov	si,offset MP_Config_Table
		mov	di,MP_ShadowTbl_Address
		mov	cx,Major_CfgTbl_Len
		cld
		rep	movsb

		mov	ax,Major_entry		;Get major entry number
;R10 start
		push	ds
		xor	si,si			;2 CPU flag of segment
		mov	ds,si			;load to DS
		cmp	byte ptr ds:[0500H],0aah;check 2 CPUs exist?
		pop	ds
		jne	short No_2_CPU		;No,skip second CPU table
		mov	si,offset Process_Entry2;Secondary process entry
		mov	cx,Process_Entry2_Len	;length
		rep	movsb			;move table to shadow
		inc	ax			;increase major entry number
No_2_CPU:
;R10 end
		xor	dh,dh			;clear DH for counter
ifdef PCI_BUS
	;copy PCI bus data to shadow buffer
		F000_call	Get_Max_PciBus	;return CL = the Maximum PCI Bus No. currently on the system
		mov	dl,cl			;set DL to Maximum PCI Bus No.
		inc	dl
		add	ax,dx			;count total entry
Fill_PCI_Loop:
		mov	si,offset PCI_Bus_Entry
		mov	bx,di
		mov	cx,Entry_Len
		rep	movsb
		mov	byte ptr es:[bx+1],dh	;fill correct BUS_ID
		inc	dh
		cmp	dh,dl
		jb	short Fill_PCI_Loop
endif ;PCI_BUS
		inc	ax			;count total entry
		mov	si,offset ISA_EISA_Bus_Entry
		mov	bx,di
		mov	cx,ENTRY_LEN
		rep	movsb
		mov	byte ptr es:[bx+1],dh	;fill correct BUS_ENTRY_ID
						;for ISA bus entry

		inc	ax			;count total entry
	;copy IO Apic data to shadow buffer
		mov	si,offset IO_Apic_Entry
		mov	cx,ENTRY_LEN
		rep	movsb

ifdef	NEW_INTEL_IOAPIC
		inc	ax			;count total entry
	;copy IRQ 0 data to shadow buffer
		mov	si,offset IO_Int_Entry
		mov	bx,di
		mov	cx,ENTRY_LEN
		rep	movsb
		mov	byte ptr es:[bx+1],TYPE_EXTINT	;I/O interrupt type
		mov	byte ptr es:[bx+4],dh	;fill ISA_BUS_ID to correct
endif	;NEW_INTEL_IOAPIC

;R06A - start		
	;save ISA/IRQ entry starting address in EBP
		rol	ebp,16			;get ebp
		mov	bp,di			;save DI
		rol	ebp,16			;shift di into ebp
;R06A - end		

		add	ax,15			;count total entry
	;copy IRQ 1-15 data to shadow buffer
		mov	dl,1			;start BUS_ENTRY_ID from 1
Fill_IRQ_Loop:
		mov	si,offset IO_Int_Entry
		mov	bx,di
		mov	cx,ENTRY_LEN
		rep	movsb
		mov	byte ptr es:[bx+4],dh	;fill ISA_BUS_ID to correct
		mov	byte ptr es:[bx+5],dl	;fill source bus IRQ
		mov	byte ptr es:[bx+7],dl	;fill destination I/O APIC INTIN#
		cmp	dl,2
		jne	short @F
		mov	byte ptr es:[bx+5],0	;set IRQ 2 source bus irq to 0
@@:
		cmp	dl,8
		jne	short @F
		mov	byte ptr es:[bx+2],5	;set IRQ 8 signal to 5
@@:
		inc	dl
		cmp	dl,10h
		jb	short Fill_IRQ_Loop

ifdef	NEW_INTEL_IOAPIC			;R12
		push	dx			;store ISA_BUS_ID
		push	ax			;store total entry
	;copy dyanmic PCI/IRQ routing table for I/O entry 16-19
		call	Dynamic_PciIrq		;return number of entry in bx
		pop	ax			;restore total entry
		pop	dx			;restore ISA_BUS_ID
		xor	bh,bh
		add	ax,bx			;count total entry

	;copy SMI entries
		call	Mps_Ver14_Or11		;check 1.4 or 1.1 	;R06
		jz	short NotVer14					;R06

 ifndef	PCI_BEHIND_P2P_USE_INTIN20_23					;R11
	;copy entry 23 for v1.4
		inc	ax			;count total entry
		mov	si,offset IO_Int_Entry23
		mov	bx,di
		mov	cx,ENTRY_LEN
		rep	movsb
		mov	byte ptr es:[bx+4],dh	;fill ISA_BUS_ID to correct
 endif;	PCI_BEHIND_P2P_USE_INTIN20_23					;R11

NotVer14:								;R06
endif;	NEW_INTEL_IOAPIC			;R12

	;copy 2 local APIC entries
		add	ax,2			;count total entry
		mov	si,offset Local_Int_Entry1
		mov	cx,ENTRY_LEN*2
		rep	movsb

;R06A - start
		call	Mps_Ver14_Or11		;check 1.4 or 1.1 	
		jnz	short NotVer11_1
	;set ISA bus ID for local INT entry if v1.1 applied
		mov	es:[di-4],dh		;change to ISA bus ID
		mov	es:[di-4-ENTRY_LEN],dh	;change to ISA bus ID
NotVer11_1:
;R06A - end

		mov	si,MP_ShadowTbl_Address
		sub	di,si			;di = MP table total length
		mov	word ptr es:[si+MPCFGLEN_LOC],di
		mov	word ptr es:[si+MPENTRY_NO_LEN],ax
ifdef	P6_BIOS_ONLY
	;build P6 CPU ID into MP table
		mov	eax,dword ptr es:[P1_SiGn] 	;get ID of CPU 1
		mov	dword ptr es:[si+Cpu1_ID_Loc],eax

;R10		mov	eax,dword ptr es:[P2_SiGn] 	;get ID of CPU 2
;R10		mov	dword ptr es:[si+Cpu2_ID_Loc],eax
		xor	ax,ax
		mov	ds,ax
		cmp	byte ptr ds:[0500H],0aah	;check 2 CPUs exist?
;R10		je	short Have_2_CPU		;Yes,2 CPUs occupy then skip
;R10		mov	byte ptr es:[si+LOCAL_APIC_ID1_Loc],0
;R10		mov	byte ptr es:[si+LOCAL_APIC_ID2_Loc],0ffh
;R10Have_2_CPU:
;R10 start
		jne	short No_2_CPUs			;No,Only 1 CPU
		mov	eax,dword ptr es:[P2_SiGn] 	;get ID of CPU 2
		mov	dword ptr es:[si+Cpu2_ID_Loc],eax
No_2_CPUs:
;R10 end
endif;	P6_BIOS_ONLY

		pop	ds
		popad
		ret
Build_MpTable	endp

;R06 - start
;Function : Check which version of MP table selected by user
;Input    : none
;Output   : zero     = use 1.1
;	    non-zero = use 1.4
Mps_Ver14_Or11	proc	near

		pushad
		mov	si,offset MP_Tbl_Item	;get CMOS value
		call	F000_GetItem_Value
		or	al,al			;zero is for ver 1.1
		popad
	
		ret
Mps_Ver14_Or11	endp
;R06 - end

ifdef	NEW_INTEL_IOAPIC			;R12
;R06A - start
;Function : Build dynamic PCI/IRQ information for MP table v1.1
;Input    : ES:DI - Point to MP table to build
;	    DH    - ISA bus ID
;Output   : BL - number of I/O entry built
BuildMpsV11	proc	near
		push	cx
		push	ax

	;check if PCI/IRQ is routed, start from PIRQ A
		mov	cx,(PIIX_ID SHL 8)+60H	;get IRQ No.
CheckNextPirqPin:
		push	dx			;save ISA bus ID
		F000_CALL Get_Ct
		pop	dx			;restore ISA bus ID
		cmp	al,2			;invalid IRQ if < 2
		jbe	short NextPirqPin
		cmp	al,15			;invalie IRQ if > 15
		ja	short NextPirqPin

	;Build entry for IRQ
		push	di
		push	cx
		mov	si,offset IO_Int_Entry16	;copy sample entry
		mov	cx,ENTRY_LEN
		rep	movsb
		pop	cx
		pop	si

		mov	es:[si+5],al		;IRQ number for MPS 1.1
		push	ax			;save IRQ number
		mov	al,cl
		sub	al,(60H-16)		;start from 16 (60h-16)
		mov	es:[si+7],al		;INTIN#
		mov	es:[si+4],dh		;source bus ID No. (ISA)
		pop	ax			;restore IRQ number
		call	KillIsaIrqEntry		;kill ISA/IRQ entry		

NextPirqPin:
		inc	cl			;next INT#
		cmp	cl,63h			;end of router ?
		jbe	short CheckNextPirqPin

		pop	ax
		pop	cx

		xor	bl,bl			;no MP entry added

		ret
BuildMpsV11	endp

;Input : AL - IRQ No. to kill the built IRQ entry
;	 DI - Last entry's offset
KillIsaIrqEntry	proc	near
		pushad
		push	ds
	       
		push	es			;set destination segment
		pop	ds			;set source segment

		mov	esi,ebp
		shr	esi,16			;get starting address 

FindMatchIrqTbl:
		cmp	[si+5],al		;source IRQ match ?
		je	short Do_MoveTbl	;yes, move table
		add	si,ENTRY_LEN
		jmp	short FindMatchIrqTbl
Do_MoveTbl:

		mov	cx,di
		sub	cx,si

		mov	di,si			;get destination
		add	si,ENTRY_LEN

		rep	movsb

		pop	ds
		popad
		sub	di,ENTRY_LEN		;put the index back one entry

		ret
KillIsaIrqEntry	endp

;R06A - end

;Function : Build dynamic PCI/IRQ information for MP table v1.4
;Input    : ES:DI - Point to MP table to build
;	    DH    - ISA bus ID
;Output   : BL - number of I/O entry built
Dynamic_PciIrq	proc	near

;R06A - start
		call	Mps_Ver14_Or11		;check 1.4 or 1.1 
		jnz	short BuildVer14 	;yes, 1.4	  
		jmp	BuildMpsV11
BuildVer14:				 	;yes, 1.4	  
;R06A - end

		push	ax			;reserve a stack buffer
		mov	ax,0B101H		;get PCI present
		push	dx			;save ISA bus ID	;R06A
		int	1AH
		pop	dx			;restore ISA bus ID	;R06A
;R06		jc	short Not_PciBios	;CL = number of last bus
		jc	Not_PciBios		;CL = number of last bus

		mov	NCR_810_FOUND[bp],cl	;max. PCI bus no.

		xor	bx,bx			;start bus number
Next_Bus_Irq:
		xor	ch,ch			;start slot, func
Scan_Next_Irq:
		test	ch,7			;check is function 0?
		jnz	short @F		;No,skip
		pop	ax			;retore stack value
		xor	al,al			;clear to 0
		push	ax			;store to stack
@@:
		mov	cl,3cH
		F000_CAll AGet_CfgSpace_Word

		or	ah,ah			;No IRQ needed ?
		jz	short Chk_Next_Dev

		cmp	ah,04H
		ja	short Chk_Next_Dev	;valid INT# is 01-04

		cmp	al,15			;valid IRQ number
		ja	short Chk_Next_Dev	;invalid if bigger than 15

		cmp	al,2			;availabe IRQ is 3-15
		jbe	short Chk_Next_Dev

		call	Ct_GetPirqNo		;whick PIRQ routed, AL=PIRQ
		jc	short Chk_Next_Dev	;no found

		push	di
		push	cx
		mov	si,offset IO_Int_Entry16
		mov	cx,ENTRY_LEN
		rep	movsb
		pop	cx
		pop	si

		mov	es:[si+4],bh		;source bus ID No.

		mov	es:[si+7],al		;INTIN#

;R06A		call	Mps_Ver14_Or11		;check 1.4 or 1.1 	;R06
;R06A		jnz	short YesVer14		;yes, 1.4		;R06

;R06A		mov	cl,3cH			;R06
;R06A		F000_CALL AGet_CfgSpace_Word	;R06
		mov	es:[si+5],al		;IRQ number for MPS 1.1
;R06A		jmp	short IrqNoDone		;R06
;R06AYesVer14:					;yes, 1.4		;R06

		pop	ax			;get slot number function NO from stack
		mov	ah,ch
		shr	ah,1
		and	ah,not 3		;mask low 2 bits to 0
		and	al,3			;only 2 bits available
		or	ah,al			;fix to correct slot number function NO
		inc	al			;point to next slot number function NO
		push	ax			;store to stack for next access
		mov	es:[si+5],ah		;slot number

IrqNoDone:					;R06
		inc	bl			;one MP entry added
Chk_Next_Dev:

		call	Get_NextPci_Dev		;CH return next device to do
		jnc	short Scan_Next_Irq

		inc	bh
		cmp	bh,NCR_810_FOUND[bp]
;R06		jbe	short Next_Bus_Irq
		jbe	Next_Bus_Irq		;R06

Not_PciBios:
		pop	ax			;balance stack point

		ret
Dynamic_PciIrq	endp

;[]================================================================[]
;Get_Next_Device:
;	This routine is used to get next device no to treat
;Input	:	CH - Slot identification Number
;Output :	NC : CH - Next Slot ID numbuer
;		CF : All slot & function spaces has scanned
;[]================================================================[]
		ALIGN	4
Get_NextPci_Dev	proc	near

		test	ch,07h			;alread a multi-function space?
		jnz	short @F		;yes, go point to next function

		mov	cl,0Eh			;read header type
		F000_CAll AGet_CfgSpace_Byte
		test	al,80H			;multi-function support?
		jnz	short @F		;yes, multi-function card!
		add	ch,7			;point to next device!
	@@:
		add	ch,1			;point to next function space
		jc	short @F		;already overflow!
		cmp	ch,(31 SHL 3)		;exceed maximum device?
		ja	short @F		;yes, tell caller error!

		clc				;success return
		ret
	@@:
		stc				;error return
		ret

Get_NextPci_Dev	endp

;R09;Function : return which PIRQ routed for input IRQ no.
;R09;Input    : AL - IRQ no.
;R09;Output   : AL - PIRQ no. 16 - PIRQ A , 17 - PIRQ B , 18 - PIRQ C , 19-PIRQ D
;R09;			   
;R09Ct_GetPirqNo	proc	near
;R09		push	cx
;R09		push	bx
;R09		push	dx			;save DX	;R06A
;R09		mov	cx,(PIIX_ID SHL 8)+60H
;R09		mov	bl,al
;R09		mov	bh,16			;assume PIRQ A
;R09
;R09Compare_Pirq:
;R09		F000_CALL Get_Ct
;R09		cmp	al,bl			;IRQ match ?
;R09		je	short Get_Pirq
;R09		inc	cx
;R09		inc	bh
;R09		cmp	cl,63h			;last IRQ routing reg.
;R09		jbe	short Compare_Pirq
;R09		stc
;R09Get_Pirq:
;R09		mov	al,bh
;R09		pop	dx			;restore DX	;R06A
;R09		pop	bx
;R09		pop	cx
;R09		ret
;R09Ct_GetPirqNo	endp

;R09 - start
;Function : return which PIRQ routed for input IRQ no.
;Input    : AL - IRQ no. AH - INT# used by device
;	    BH - Bus number.
;	    CH - Device No.(Top 5 bits)+Function No. (lower 3 bits)
;Output   : AL - PIRQ no. 16 - PIRQ A , 17 - PIRQ B , 18 - PIRQ C , 19-PIRQ D
;	    carry set - no match PIRQ#		   
Ct_GetPirqNo	proc	near

		push	si
		push	di
		push	bx
		push	cx
		push	ds

		push	0F000H
		pop	ds		;DS = 0F000H

		or	bh, bh		;bus 0 ?
		jz	short YesBus0	;

		call	IrqMapForNonBus0;find the mother slot for subordinate
					;bus.

YesBus0:
		shr	ch, 3		;need device number only
		call	GetBus0Route	;get IRQ rounting value
	   
		pop	ds
		pop	cx
		pop	bx
		pop	di
		pop	si

		ret
Ct_GetPirqNo	endp

;Function : Covert INT# for Non PCI bus 0 devices
;Input : BH - bus number
;	 AH - INT# of the PCI device connected.
;	 CH - device number (bit4-0)
;Output: AH - INT# converted for bus 0
; 	 CH - mother slot device number on bus 0
;
IrqMapForNonBus0	proc	near

		push	dword ptr NCR_810_FOUND[bp]
		mov	NCR_810_FOUND[bp], bh
		mov	NCR_810_FOUND[bp+1], ch	;device number
		mov	NCR_810_FOUND[bp+2], ah	;INT#

FindPrvPciBus:
		
		xor	si, si		;start from first device
FindNextP2P:
		mov	ecx, 060400H	;P2P bridge
		mov	ax, 0b103H	;find PCI class code
		int	1AH		;invoke PCI BIOS interface

		jc	short NoClassFound

		mov	di, 18H		;read Sec. & Prim. bus number
		mov	ax, 0b109H	;read PCI word
		int	1AH		;invoke PCI BIOS interface

		cmp	ch, NCR_810_FOUND[bp]	;secondary bus No. match ?
		je	short CheckPrimBus

		inc	si		;next P2P device,until bus number
		jmp	short FindNextP2P;is match.

CheckPrimBus:


	;Convert INT# due to P2P IRQ routing spec.
		mov	al, NCR_810_FOUND[bp+1]	;get device number
		shr	al, 3
		and	al, 11B
		mov	ah, NCR_810_FOUND[bp+2]	;INT#
		add	ah, al
		cmp	ah, 4			;max. is INTD
		jbe	short GoodINT
		sub	ah, 4
GoodINT:
		mov	NCR_810_FOUND[bp+2], ah	;INT#

		or	cl, cl		;reach bus 0 ?
		jz	short YesPciBus0

		mov	NCR_810_FOUND[bp+1], bl	;current P2P's device number
		mov	NCR_810_FOUND[bp], cl  	;search next P2P , until
		jmp	short FindPrvPciBus	;bus 0 is reached.

YesPciBus0:
		mov	ch, bl		;get device & function number
		mov	ah, NCR_810_FOUND[bp+2];get converted INT#

NoClassFound:
		pop	dword ptr NCR_810_FOUND[bp]

		ret
IrqMapForNonBus0	endp

;Function : return which PIRQ routed for input INT#
;Input    : AH - INT# used by device
;	    BH - 0 (bus 0)
;	    CH - Device No.(Top 5 bits)+Function No. (lower 3 bits)
;Output   : AL - PIRQ no. 16 - PIRQ A , 17 - PIRQ B , 18 - PIRQ C , 19-PIRQ D
;	    carry set - no match PIRQ#		   
GetBus0Route	proc	near
	;search PCI IRQ routing value for bus 0
		xor	bx, bx		;start from first PCI slot
		mov	si, offset PCI_SLOT_CFG

ChkNSlot:
		mov	al, ds:[bx+si]	;get slot device number
		cmp	ch, al		;device match ?
		je	short GetIrqRout

		inc	bl		;go next slot
		cmp	al, 0ffh	;end of slot ?
		jne	short ChkNSlot	;no search next slot

		stc
		jmp	short DevNotFound

GetIrqRout:
		mov	si, offset IrqRout_Table;routing table
		shl	bx, 2		;4 bytes for each routing
		dec	ah
		shr	ax, 8		;get INT#(INTA=1, INTB=2, etc..)
		add	bx, ax		;which 
		mov	al, ds:[bx+si]
		add	al, 15		;PIRQA = 16

;R11 - start
 ifdef	PCI_BEHIND_P2P_USE_INTIN20_23
		cmp	ch, P2P_PCI_DEVNO	;P2P slot ?
		jne	short NotP2PSlot
		add	al, 4			;for INTIN 20-23 routing
	NotP2PSlot:
 endif;	PCI_BEHIND_P2P_USE_INTIN20_23
;R11 - end

		clc
DevNotFound:
		ret
GetBus0Route	endp

;R09 - end
endif;	NEW_INTEL_IOAPIC			;R12

		public	MP_Config_Table
		public	MP_CFG_CHKSUM

ISA_BUS_ID	EQU	1	
PCI_BUS_ID	EQU	0	


MPCFGLEN_LOC	EQU	4
MPENTRY_NO_LEN	EQU	offset Total_Entry_Loc - offset MP_Config_Table
MP_CFG_CHKSUM	EQU	07H
MP_Config_Table:
		db	'PCMP'			;signature of MP table
		dw	0			;total length of MP table
		db	01h			;version of MP specification
		db	00h			;check sum
		db	'OEM00000'  		;OEM string
		db	'PROD00000000'		;product family
		dw	0			;OEM table pointer addr. low
		dw	0			;OEM table pointer addr. high
		dw	0			;OEM table size
Total_Entry_Loc:
		dw	0			;entry count
		dd	0fee00000h		;local APIC address
		dd	0			;reserved

PROC_TYPE	EQU	00H
LOCAL_APIC_VER1	EQU	11H
CPU_FLAG1	EQU	03H

ifdef	P6_BIOS_ONLY					
LOCAL_APIC_ID1	EQU	0
CPU_SIGNATURE1	EQU	00000616H	;for P6		
FEATURE_FLAGS1	EQU	0000fbffH			
else;	P6_BIOS_ONLY					
LOCAL_APIC_ID1	EQU	00H				
CPU_SIGNATURE1	EQU	00000521H
FEATURE_FLAGS1	EQU	000007bfH
endif;	P6_BIOS_ONLY					

Major_entry	=	0
Process_Entry1:
		db	PROC_TYPE		;process entry
LOCAL_APIC_ID1_Loc	equ	($ - offset MP_Config_Table)
		db	LOCAL_APIC_ID1		;local APIC ID number
		db	LOCAL_APIC_VER1		;local APIC ID version
		db	CPU_FLAG1		;CPU flag
Cpu1_ID_Loc	EQU	($ - offset MP_Config_Table)
		dd	CPU_SIGNATURE1		;CPU signature
		dd	FEATURE_FLAGS1		;
		dd	0			;reserved
		dd	0			;reserved
Major_entry	=	Major_entry+1
Major_CfgTbl_Len	equ	$-offset MP_Config_Table	;R10

LOCAL_APIC_VER2	EQU	11H
CPU_FLAG2	EQU	01H

ifdef	P6_BIOS_ONLY					
LOCAL_APIC_ID2	EQU	1
CPU_SIGNATURE2	EQU	00000617H	;for P6		
FEATURE_FLAGS2	EQU	0000fbffH			
else;	P6_BIOS_ONLY					
LOCAL_APIC_ID2	EQU	01H				
CPU_SIGNATURE2	EQU	00000521H
FEATURE_FLAGS2	EQU	000007bfH
endif;	P6_BIOS_ONLY			

Process_Entry2:
		db	PROC_TYPE		;process entry
LOCAL_APIC_ID2_Loc	equ	($ - offset MP_Config_Table)
		db	LOCAL_APIC_ID2		;local APIC ID number
		db	LOCAL_APIC_VER2		;local APIC ID version
		db	CPU_FLAG2		;CPU flag
Cpu2_ID_Loc	EQU	($ - offset MP_Config_Table)
		dd	CPU_SIGNATURE2		;CPU signature
		dd	FEATURE_FLAGS2		;
		dd	0			;reserved
		dd	0			;reserved
;R10 Major_entry	=	Major_entry+1
Process_Entry2_Len	equ	$ - offset Process_Entry2	;R10

ifdef	FOUR_CPUS_SYSTEM
LOCAL_APIC_ID3	EQU	02H				
Process_Entry3:
		db	PROC_TYPE		;process entry
		db	LOCAL_APIC_ID3		;local APIC ID number
		db	LOCAL_APIC_VER1		;local APIC ID version
		db	CPU_FLAG1		;CPU flag
Cpu3_ID_Loc	EQU	($ - offset MP_Config_Table)
		dd	CPU_SIGNATURE1		;CPU signature
		dd	FEATURE_FLAGS1		;
		dd	0			;reserved
		dd	0			;reserved
;R10 Major_entry	=	Major_entry+1

LOCAL_APIC_ID4	EQU	04H				
Process_Entry4:
		db	PROC_TYPE		;process entry
		db	LOCAL_APIC_ID4		;local APIC ID number
		db	LOCAL_APIC_VER1		;local APIC ID version
		db	CPU_FLAG1		;CPU flag
Cpu4_ID_Loc	EQU	($ - offset MP_Config_Table)
		dd	CPU_SIGNATURE1		;CPU signature
		dd	FEATURE_FLAGS1		;
		dd	0			;reserved
		dd	0			;reserved
;R10 Major_entry	=	Major_entry+1
endif;	FOUR_CPUS_SYSTEM
;R10 Major_CfgTbl_Len	equ	$-offset MP_Config_Table

BUS_ENTRY_ID	EQU	01H
PCI_Bus_Entry:
		db	BUS_ENTRY_ID		;bus entry ID
		db	PCI_BUS_ID					
		db	'PCI   '		;bus type string	

ISA_EISA_Bus_Entry:
		db	BUS_ENTRY_ID		;bus entry ID
		db	ISA_BUS_ID					
if 	BUS_TYPE EQ EISA_BUS						 
		db	'EISA  '		;bus type string	 
else 	;BUS_TYPE EQ EISA_BUS						 
		db	'ISA   '		;bus type string	 
endif 	;BUS_TYPE EQ EISA_BUS						 

IO_APIC_ID	EQU	02H
APIC_ENTRY_ID	EQU	02H
IO_Apic_Entry:
		db	APIC_ENTRY_ID		;I/O APIC ID
		db	IO_APIC_ID		;I/O apic id
		db	11H			;I/O apic version
		db	01H			;I/O apic flag
		dd	0fec00000h		;I/O apic address

IOInt_Entry_ID	EQU	03H
TYPE_INT	EQU	0
TYPE_NMI	EQU	1
TYPE_SMI	EQU	2
TYPE_EXTINT	EQU	3

IO_Int_Entry:
		db	IOInt_Entry_ID		;I/O interrupt entry ID
		db	TYPE_INT		;I/O interrupt type
		dw	0000H			;active high & edge trigger
		db	ISA_BUS_ID
		db	0			;source bus IRQ
		db	IO_APIC_ID     		;destination I/O APIC ID
		db	0			;destination I/O APIC INTIN#

;Interrupt entry for local APIC

LOCAL_INT_ENTRY_ID	EQU	04H
Local_Int_Entry1:
		db	LOCAL_INT_ENTRY_ID	;local interrupt entry ID
		db	TYPE_EXTINT		;interrupt type
		dw	0
		db	PCI_BUS_ID
		db	0			;source bus IRQ
		db	0FFH			;destination LOCAL APIC ID
		db	0			;destination LOCAL APIC INTIN#

Local_Int_Entry2:
		db	LOCAL_INT_ENTRY_ID	;local interrupt entry ID
		db	TYPE_NMI		;interrupt type
		dw	0
		db	PCI_BUS_ID
		db	0			;source bus IRQ
		db	0FFH			;destination I/O APIC ID
		db	1			;destination I/O APIC INTIN#

ifdef	NEW_INTEL_IOAPIC
;Interrupt entry for PCI IRQ routing
		public	IO_Int_Entry16
		public	IO_Int_Entry17
		public	IO_Int_Entry18
		public	IO_Int_Entry19
IO_Int_Entry16:					;PIRQ A
IO_Int_Entry17:					;PIRQ B
IO_Int_Entry18:					;PIRQ C
IO_Int_Entry19:					;PIRQ D
		db	IOInt_Entry_ID		;I/O interrupt entry ID
		db	TYPE_INT		;I/O interrupt type
		dw	000FH			;active low & level trigger
		db	PCI_BUS_ID		
		db	(SLOT1_ID SHL 2)+0 	;source bus IRQ,PIRQ 0
		db	IO_APIC_ID	  	;destination I/O APIC ID
		db	16			;destination I/O APIC INTIN#

IO_Int_Entry23:					;for SMI
		db	IOInt_Entry_ID		;I/O interrupt entry ID
		db	TYPE_SMI		;I/O interrupt type
		dw	0000H			;active low & level trigger
		db	ISA_BUS_ID
		db	0			;source bus IRQ
		db	IO_APIC_ID	  	;destination I/O APIC ID
		db	23			;destination I/O APIC INTIN#


endif;	NEW_INTEL_IOAPIC

endif;	MP_SUPPORT


ECODE		ENDS

		END
