;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; RDOS operating system ; Copyright (C) 1988-2000, Leif Ekblad ; ; This program is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2 of the License, or ; (at your option) any later version. The only exception to this rule ; is for commercial usage in embedded systems. For information on ; usage in commercial embedded systems, contact embedded@rdos.net ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ; ; The author of this program may be contacted at leif@rdos.net ; ; apic.asm ; APIC module ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INCLUDE ..\os.def INCLUDE ..\os.inc INCLUDE ..\driver.def INCLUDE ..\os\port.def INCLUDE ..\os\system.def INCLUDE apic.inc INCLUDE ..\os\protseg.def INCLUDE ..\os\core.inc INCLUDE ..\acpi\acpitab.inc INCLUDE ..\os\realmon.def INCLUDE ..\bios\vbe.inc INCLUDE ..\user.def INCLUDE ..\user.inc ioapic_data_seg STRUC ioapic_regsel DB ? ioapic_resv DB 15 DUP(?) ioapic_window DD ? ioapic_data_seg ENDS global_int_struc STRUC gi_handler_sel DW ? gi_ioapic_sel DW ? gi_long_ads DD ? gi_ioapic_id DB ? gi_int_num DB ? gi_prio DB ? gi_trigger_mode DB ? global_int_struc ENDS ioapic_core_irq_struc STRUC ioapic_sel DW ? ioapic_num DB ? ioapic_core_irq_struc ENDS data SEGMENT byte public 'DATA' bsp_id DD ? ioapic_spinlock DW ? detected_irqs DD ?,? ioapic_count DW ? ioapic_arr DW 16 DUP(?) redir_arr DB 16 DUP(?) global_int_arr DD 256 DUP(?,?,?,?) data ENDS IFDEF __WASM__ .686p .xmm2 ELSE .386p ENDIF code SEGMENT byte public use32 'CODE' assume cs:code extern GetAcpiTable:near extern GetApicTable:near ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: LockIoApic ; ; DESCRIPTION: Lock IO-APIC ; ; PARAMETERS: DS SEG data ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; LockIoApic MACRO local SpinLock local Get SpinLock: mov ax,ds:ioapic_spinlock or ax,ax je Get ; sti pause jmp SpinLock Get: cli inc ax xchg ax,ds:ioapic_spinlock or ax,ax jne SpinLock ENDM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: UnlockIoApic ; ; DESCRIPTION: Unlock IO-APIC ; ; PARAMETERS: DS SEG data ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; UnlockIoApic MACRO mov ds:ioapic_spinlock,0 sti ENDM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: Get IOAPIC state ; ; DESCRIPTION: Get state for IOAPIC int ; ; PARAMETERS: AL Global int # ; ; RETURNS: EDX:EAX IOAPIC entry ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_ioapic_state_name DB 'Get IO-APIC State',0 get_ioapic_state Proc far push ds push fs push ebx ; mov ebx,apic_mem_sel mov ds,ebx mov ebx,APIC_ISR + 50h mov edx,ds:[ebx] ; mov bx,APIC_IRR + 50h mov edx,ds:[ebx] ; mov ebx,SEG data mov ds,ebx ; movzx ebx,al shl ebx,4 add ebx,OFFSET global_int_arr ; mov al,ds:[ebx].gi_ioapic_id mov fs,ds:[ebx].gi_ioapic_sel ; mov bl,10h add bl,al add bl,al ; LockIoApic mov fs:ioapic_regsel,bl mov eax,fs:ioapic_window ; inc bl mov fs:ioapic_regsel,bl mov edx,fs:ioapic_window UnlockIoApic ; pop ebx pop fs pop ds ret get_ioapic_state Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddIoApicHandler ; ; DESCRIPTION: Add core mover for IO-APIC ; ; PARAMETERS: AL IO-APIC entry ; FS IO-APIC selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddIoApicHandler Proc near push es ; push eax mov eax,SIZE ioapic_core_irq_struc AllocateSmallGlobalMem pop eax ; mov es:ioapic_sel,fs mov es:ioapic_num,al ; pop es ret AddIoApicHandler Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ISA IRQ handler ; ; DESCRIPTION: Code for patching into ISA (edge mode) IRQ handler ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; this code should not contain near jumps or references to near labels! isa_irq_handler_struc STRUC isa_irq_linear DD ? isa_irq_handler_ads DD ?,? isa_irq_handler_data DW ? isa_irq_type DW ? isa_irq_chain DW ? isa_irq_nr DB ? isa_irq_detect_nr DB ? isa_irq_handler_struc ENDS IsaIrqStart: isa_irq_handler isa_irq_handler_struc <> IsaIrqEntry: pushad push ds push es push fs ; mov al,cs:isa_irq_nr EnterInt ; mov ax,word ptr fs:cs_curr_irq_nr or ax,ax jz IsaIrqPrevOk ; mov ax,fs:cs_nested_irq_count mov bx,ax inc ax cmp ax,MAX_IRQ_NESTING jne IsaIrqAddStack ; int 3 IsaIrqAddStack: mov fs:cs_nested_irq_count,ax ; shl bx,2 mov eax,dword ptr fs:cs_curr_irq_nr mov fs:[bx].cs_nested_irq_stack,eax IsaIrqPrevOk: movzx bx,cs:isa_irq_nr mov word ptr fs:cs_curr_irq_nr,bx mov fs:cs_curr_irq_retries,0 ; sti IsaIrqRetry: mov ds,cs:isa_irq_handler_data call fword ptr cs:isa_irq_handler_ads ; mov bx,OFFSET IsaIrqEnd - OFFSET IsaIrqStart jmp cs:isa_irq_chain IsaIrqExit: cli ; mov ax,word ptr fs:cs_curr_irq_nr or ah,ah jz IsaIrqExitCountOk ; mov fs:cs_curr_irq_count,0 mov al,fs:cs_curr_irq_retries inc al mov fs:cs_curr_irq_retries,al ; sti cmp al,100 jne IsaIrqRetry ; int 3 jmp IsaIrqRetry IsaIrqExitCountOk: mov word ptr fs:cs_curr_irq_nr,0 mov bx,fs:cs_nested_irq_count or bx,bx jz IsaIrqExitNestingOk ; dec bx mov fs:cs_nested_irq_count,bx shl bx,2 mov eax,fs:[bx].cs_nested_irq_stack mov dword ptr fs:cs_curr_irq_nr,eax IsaIrqExitNestingOk: mov eax,apic_mem_sel mov ds,eax xor eax,eax mov ds:APIC_EOI,eax LeaveInt ; pop eax verr ax jz IrqExitFs ; xor eax,eax IrqExitFs: mov fs,eax ; pop eax verr ax jz IrqExitEs ; xor eax,eax IrqExitEs: mov es,eax ; pop eax verr ax jz IrqExitDs ; xor eax,eax IrqExitDs: mov ds,eax ; popad iretd IsaIrqDetect: mov ax,SEG data mov ds,ax movzx bx,cs:isa_irq_detect_nr shl bx,4 add bx,OFFSET global_int_arr mov al,ds:[bx].gi_ioapic_id mov es,ds:[bx].gi_ioapic_sel ; mov bl,10h add bl,al add bl,al ; LockIoApic mov es:ioapic_regsel,bl mov eax,10000h mov es:ioapic_window,eax ; inc bl mov es:ioapic_regsel,bl xor eax,eax mov es:ioapic_window,eax UnlockIoApic ; movzx dx,cs:isa_irq_detect_nr cmp dx,64 jae IsaIrqDetectDone ; mov bx,OFFSET detected_irqs bts ds:[bx],dx IsaIrqDetectDone: retf IsaIrqEnd: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ISA IRQ chaining ; ; DESCRIPTION: Code for adding at end of ISA IRQ handler in order to chain ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; this code should not contain near jumps or references to near labels! isa_irq_chain_struc STRUC isa_irch_handler_ads DD ?,? isa_irch_handler_data DW ? isa_irch_chain DW ? isa_irq_chain_struc ENDS IsaIrqChainStart: isa_irch_handler isa_irq_chain_struc <> IsaIrqChainEntry: push bx mov ds,cs:[bx].isa_irch_handler_data call fword ptr cs:[bx].isa_irch_handler_ads pop bx ; mov si,bx add bx,OFFSET IsaIrqChainEnd - OFFSET IsaIrqChainStart jmp cs:[si].isa_irch_chain IsaIrqChainEnd: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CreateIsaIrq ; ; DESCRIPTION: Create new ISA IRQ context ; ; PARAMETERS: AL IRQ # ; ; RETURNS: DS:ESI Address of entry-point ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CreateIsaIrq Proc near push es push eax push ebx push ecx push edx push edi ; push eax mov eax,OFFSET IsaIrqEnd - OFFSET IsaIrqStart AllocateSmallLinear AllocateGdt mov ecx,eax CreateCodeSelector32 ; mov eax,cs mov ds,eax mov eax,flat_sel mov es,eax mov esi,OFFSET IsaIrqStart mov edi,edx rep movs byte ptr es:[edi],ds:[esi] ; mov es:[edx].isa_irq_linear,edx mov word ptr es:[edx].isa_irq_chain,OFFSET IsaIrqExit - OFFSET IsaIrqStart mov dword ptr es:[edx].isa_irq_handler_ads,OFFSET IsaIrqDetect - OFFSET IsaIrqStart mov word ptr es:[edx].isa_irq_handler_ads+4,bx mov es:[edx].isa_irq_handler_data,0 pop eax mov es:[edx].isa_irq_nr,al mov es:[edx].isa_irq_detect_nr,al mov es:[edx].isa_irq_type,IRQ_TYPE_ISA ; mov ds,bx mov esi,OFFSET IsaIrqEntry - OFFSET IsaIrqStart ; pop edi pop edx pop ecx pop ebx pop eax pop es ret CreateIsaIrq Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ForceLevelIrq ; ; DESCRIPTION: Force IRQ to level triggered mode ; ; PARAMETERS: AL Global int # ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; force_level_irq_name DB 'Force Level IRQ',0 force_level_irq Proc far push ds push eax push ebx ; mov ebx,SEG data mov ds,ebx movzx ebx,al shl ebx,4 add ebx,OFFSET global_int_arr mov [ebx].gi_trigger_mode,0A0h ; pop ebx pop eax pop ds ret force_level_irq Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: RequestIrqHandler ; ; DESCRIPTION: Request ISA IRQ-based interrupt-handler ; ; PARAMETERS: DS Data passed to handler ; ES:EDI Handler address ; AL Global int # ; AH Priority ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; request_irq_handler_name DB 'Request ISA IRQ Handler',0 request_irq_handler Proc far push fs pushad ; movzx ebx,al shl ebx,4 mov edx,SEG data mov fs,edx mov esi,fs:[ebx].global_int_arr.gi_long_ads mov bx,fs:[ebx].global_int_arr.gi_handler_sel or bx,bx jz rihDone ; cmp ah,31 jbe rihPrioHighOk ; mov ah,31 rihPrioHighOk: or ah,ah jne rihPrioLowOk ; mov ah,1 rihPrioLowOk: push eax ; or esi,esi jz rihLongOk ; AddLongIrq rihLongOk: mov fs,ebx mov edx,fs:isa_irq_linear mov eax,flat_sel mov fs,eax ; mov al,fs:[edx].isa_irq_detect_nr cmp al,-1 jne rihReplace rihChain: push ds push es push ecx push esi push edi ; mov eax,flat_sel mov ds,eax mov es,eax ; mov esi,edx GetSelectorBaseSize push ecx mov eax,ecx add eax,OFFSET IsaIrqChainEnd - OFFSET IsaIrqChainStart AllocateSmallLinear push edx mov edi,edx rep movs byte ptr es:[edi],ds:[esi] mov ebp,edi ; xchg edx,ds:[edx].isa_irq_linear xor ecx,ecx FreeLinear ; mov eax,cs mov ds,eax mov esi,OFFSET IsaIrqChainStart mov ecx,OFFSET IsaIrqChainEnd - OFFSET IsaIrqChainStart rep movs byte ptr es:[edi],ds:[esi] ; pop edx pop ecx add ecx,OFFSET IsaIrqChainEnd - OFFSET IsaIrqChainStart CreateCodeSelector32 ; pop edi pop esi pop ecx pop es pop ds ; mov fs:[ebp].isa_irch_handler_data,ds mov fs:[ebp].isa_irch_handler_ads,edi mov word ptr fs:[ebp].isa_irch_handler_ads+4,es mov eax,ebp sub eax,edx add eax,OFFSET IsaIrqChainEntry - OFFSET IsaIrqChainStart sub eax,OFFSET IsaIrqChainEnd - OFFSET IsaIrqChainStart cmp eax,OFFSET IsaIrqEnd - OFFSET IsaIrqStart jae rihChainPrev ; add eax,OFFSET IsaIrqChainEnd - OFFSET IsaIrqChainStart xchg ax,fs:[edx].isa_irq_chain mov fs:[ebp].isa_irch_chain,ax jmp rihChainDone rihChainPrev: mov edx,ebp sub edx,OFFSET IsaIrqChainEnd - OFFSET IsaIrqChainStart add eax,OFFSET IsaIrqChainEnd - OFFSET IsaIrqChainStart xchg ax,fs:[edx].isa_irch_chain mov fs:[ebp].isa_irch_chain,ax jmp rihChainDone rihReplace: mov fs:[edx].isa_irq_handler_data,ds mov fs:[edx].isa_irq_handler_ads,edi mov word ptr fs:[edx].isa_irq_handler_ads+4,es mov fs:[edx].isa_irq_detect_nr,-1 rihChainDone: pop eax ; movzx ebx,al shl ebx,4 add ebx,OFFSET global_int_arr mov edx,SEG data mov fs,edx mov dl,fs:[ebx].gi_prio cmp ah,dl jbe rihDone ; mov fs:[ebx].gi_prio,ah mov al,fs:[ebx].gi_int_num FreeInt rihChangePrio: mov al,fs:[ebx].gi_prio mov cx,1 AllocateInts jnc rihPrioOk ; dec fs:[ebx].gi_prio jmp rihChangePrio rihPrioOk: push ds push ebx ; mov esi,fs:[ebx].gi_long_ads or esi,esi jz rihLongPrioOk ; push ebx xor bl,bl SetupLongIntGate pop ebx rihLongPrioOk: mov ds,fs:[ebx].gi_handler_sel mov esi,OFFSET IsaIrqEntry - OFFSET IsaIrqStart xor bl,bl SetupIntGate ; pop ebx pop ds ; mov fs:[ebx].gi_int_num,al ; push ds mov eax,SEG data mov ds,eax ; mov al,fs:[ebx].gi_ioapic_id movzx edx,fs:[ebx].gi_int_num mov dh,fs:[ebx].gi_trigger_mode mov fs,fs:[ebx].gi_ioapic_sel call AddIoApicHandler ; mov bl,10h add bl,al add bl,al ; LockIoApic mov fs:ioapic_regsel,bl mov fs:ioapic_window,edx ; inc bl mov fs:ioapic_regsel,bl ; mov edx,ds:bsp_id shl edx,24 mov fs:ioapic_window,edx UnlockIoApic pop ds rihDone: popad pop fs ret request_irq_handler Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SetupLocalApic ; ; DESCRIPTION: Setup local APIC ; ; PARAMETERS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; public SetupLocalApic SetupLocalApic Proc near push es push eax push ebx ; mov ebx,apic_mem_sel mov es,ebx ; mov eax,10000h mov es:APIC_LINT0,eax ; mov eax,10000h mov es:APIC_LINT1,eax ; mov eax,10000h mov es:APIC_LERROR,eax ; mov eax,10000h mov es:APIC_THERMAL,eax ; mov eax,10000h mov es:APIC_PERF,eax ; mov eax,10000h mov es:APIC_TIMER,eax ; mov eax,es:APIC_SPUR and eax,NOT 1000h or eax,100h mov al,0Fh mov es:APIC_SPUR,eax ; mov eax,0Bh mov es:APIC_DIV_CONFIG,eax ; mov eax,-1 mov es:APIC_DEST_FORMAT,eax ; mov eax,10000000h mov es:APIC_LOG_DEST,eax ; xor eax,eax mov es:APIC_TPR,eax ; pop ebx pop eax pop es ret SetupLocalApic Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SendEoi ; ; DESCRIPTION: Send EOI to APIC (only use for custom ISRs) ; ; PARAMETERS: AL Int ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; send_eoi_name DB 'Send EOI',0 send_eoi Proc far push ds push eax ; mov eax,apic_mem_sel mov ds,eax xor eax,eax mov ds:APIC_EOI,eax ; pop eax pop ds ret send_eoi Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: NotifyIrq ; ; DESCRIPTION: Notify IRQ occurred ; ; PARAMETERS: AL Int ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; notify_irq_name DB 'Notify IRQ',0 notify_irq Proc far push ds push es push eax push ebx push edx ; push eax movzx ebx,al mov eax,SEG data mov ds,eax shl ebx,4 add ebx,OFFSET global_int_arr mov al,ds:[ebx].gi_ioapic_id mov dx,ds:[ebx].gi_ioapic_sel or dx,dx jz niNoIoApic ; mov es,edx mov bl,10h add bl,al add bl,al ; LockIoApic mov es:ioapic_regsel,bl mov eax,10000h mov es:ioapic_window,eax ; inc bl mov es:ioapic_regsel,bl xor eax,eax mov es:ioapic_window,eax UnlockIoApic niNoIoApic: pop eax ; movzx edx,al cmp edx,64 jae niDone ; mov ebx,OFFSET detected_irqs bts ds:[ebx],edx niDone: pop edx pop ebx pop eax pop es pop ds ret notify_irq Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: EnableDetect ; ; Description: Enable IRQ detect ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EnableDetect Proc near push ds push es pushad ; mov eax,SEG data mov ds,eax mov ecx,64 mov esi,OFFSET global_int_arr edLoop: mov dl,ds:[esi].gi_prio or dl,dl jnz edNext ; mov dx,ds:[esi].gi_ioapic_sel or dx,dx jz edNext ; mov es,dx movzx edx,ds:[esi].gi_int_num mov dh,ds:[esi].gi_trigger_mode mov al,ds:[esi].gi_ioapic_id ; mov bl,10h add bl,al add bl,al ; LockIoApic mov es:ioapic_regsel,bl mov es:ioapic_window,edx ; inc bl mov es:ioapic_regsel,bl ; mov edx,ds:bsp_id shl edx,24 mov es:ioapic_window,edx UnlockIoApic edNext: add esi,16 loop edLoop ; popad pop es pop ds ret EnableDetect Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: setup_irq_detect ; ; description: Setup IRQ detect ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; setup_irq_detect_name DB 'Setup IRQ detect',0 setup_irq_detect Proc far push ds push eax ; mov eax,SEG data mov ds,eax mov ds:detected_irqs,0 call EnableDetect ; mov ax,1 WaitMilliSec ; mov ds:detected_irqs,0 mov ds:detected_irqs+4,0 ; pop eax pop ds ret setup_irq_detect Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: poll_irq_detect ; ; description: Poll detected IRQs ; ; RETURNS: EAX Detected IRQs ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; poll_irq_detect_name DB 'Poll IRQ detect',0 poll_irq_detect Proc far push ds ; mov eax,SEG data mov ds,eax mov eax,ds:detected_irqs mov edx,ds:detected_irqs+4 ; pop ds ret poll_irq_detect Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: DisableAllIrq ; ; description: Disable all IRQs in APIC controller ; ; RETURNS: EAX Active IRQs ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; disable_all_irq_name DB 'Disable All IRQs', 0 disable_all_irq Proc far push ds push ebx push ecx push esi ; mov eax,apic_mem_sel mov ds,eax mov eax,10000h mov ds:APIC_TIMER,eax ; mov eax,SEG data mov ds,eax ; movzx ecx,ds:ioapic_count mov esi,OFFSET ioapic_arr daiApicLoop: push ds push ecx mov ds,ds:[esi] ; mov ecx,24 mov bl,10h daiLoop: mov ds:ioapic_regsel,bl mov eax,10000h mov ds:ioapic_window,eax ; inc bl mov ds:ioapic_regsel,bl xor eax,eax mov ds:ioapic_window,eax inc bl loop daiLoop ; pop ecx pop ds add esi,2 loop daiApicLoop ; call SetupLocalApic ; mov eax,apic_mem_sel mov ds,eax mov eax,ds:APIC_ISR + 20h ; pop esi pop ecx pop ebx pop ds ret disable_all_irq Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SpuriousInt ; ; DESCRIPTION: Spurious int ; ; PARAMETERS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; spurious_int: iretd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: tlb_int ; ; DESCRIPTION: TLB invalidate int ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; tlb_int: pushad push ds push es push fs push gs ; mov al,-1 EnterInt mov eax,apic_mem_sel mov ds,eax xor eax,eax mov ds:APIC_EOI,eax LeaveInt ; pop eax verr ax jz TlbExitGs ; xor eax,eax TlbExitGs: mov gs,eax ; pop eax verr ax jz TlbExitFs ; xor eax,eax TlbExitFs: mov fs,eax ; pop eax verr ax jz TlbExitEs ; xor eax,eax TlbExitEs: mov es,eax ; pop eax verr ax jz TlbExitDs ; xor eax,eax TlbExitDs: mov ds,eax popad iretd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: wakeup_int ; ; DESCRIPTION: Wakeup int ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; wakeup_int: pushad push ds push es push fs push gs ; mov al,-1 EnterInt mov eax,apic_mem_sel mov ds,eax xor eax,eax mov ds:APIC_EOI,eax IpiWakeup LeaveInt ; pop eax verr ax jz WiExitGs ; xor eax,eax WiExitGs: mov gs,eax ; pop eax verr ax jz WiExitFs ; xor eax,eax WiExitFs: mov fs,eax ; pop eax verr ax jz WiExitEs ; xor eax,eax WiExitEs: mov es,eax ; pop eax verr ax jz WiExitDs ; xor eax,eax WiExitDs: mov ds,eax popad iretd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SetupInts ; ; DESCRIPTION: Setup ints ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SetupInts Proc near push ds pushad mov eax,cs mov ds,eax xor bl,bl ; mov al,0Fh mov esi,OFFSET spurious_int SetupIntGate ; mov ax,setup_long_spurious_int_nr IsValidOsGate jc siSpurOk ; mov al,0Fh SetupLongSpuriousInt siSpurOk: mov al,25h mov esi,OFFSET tlb_int SetupIntGate ; mov al,26h mov esi,OFFSET wakeup_int SetupIntGate ; popad pop ds ret SetupInts Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: InitIoApic ; ; DESCRIPTION: Init IO-APIC ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; InitIoApic Proc near mov ax,SEG data mov ds,ax mov ds:ioapic_count,0 ; mov ax,SEG data mov es,ax mov ecx,256 * 4 xor eax,eax mov edi,OFFSET global_int_arr rep stosd ; call GetApicTable ; mov ecx,16 mov edi,OFFSET global_int_arr init_ioapic_isa_trigger_mode: mov ds:[edi].gi_trigger_mode,0 mov ds:[edi].gi_long_ads,0 add edi,16 loop init_ioapic_isa_trigger_mode ; mov ecx,256-16 init_ioapic_pci_trigger_mode: mov [edi].gi_trigger_mode,0A0h add edi,16 loop init_ioapic_pci_trigger_mode ; mov eax,1000h AllocateBigLinear mov eax,es:apic_phys or ax,33h xor ebx,ebx SetPageEntry mov bx,apic_mem_sel mov ecx,1000h CreateDataSelector16 ; mov edi,OFFSET apic_entries movzx ecx,es:act_size sub ecx,OFFSET apic_entries - OFFSET apic_phys init_ioapic_table_loop: mov al,es:[edi].apic_type cmp al,1 jne init_ioapic_table_next ; push ecx mov eax,1000h AllocateBigLinear mov eax,es:[edi].aio_phys or ax,33h xor ebx,ebx SetPageEntry AllocateGdt mov ecx,1000h CreateDataSelector16 mov ax,bx ; push ds mov ds,ax mov ds:ioapic_regsel,1 mov ecx,ds:ioapic_window shr ecx,16 inc ecx pop ds ; movzx ebx,ds:ioapic_count add ebx,ebx mov ds:[ebx].ioapic_arr,ax inc ds:ioapic_count ; mov ebx,es:[edi].aio_int_base shl ebx,4 add ebx,OFFSET global_int_arr xor dl,dl init_ioapic_loop: mov ds:[ebx].gi_ioapic_sel,ax mov ds:[ebx].gi_ioapic_id,dl add ebx,16 inc dl loop init_ioapic_loop ; pop ecx init_ioapic_table_next: movzx eax,es:[edi].apic_len add edi,eax sub ecx,eax ja init_ioapic_table_loop ; GetApicId mov ds:bsp_id,edx ret InitIoApic Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CreateIrqHandlers ; ; DESCRIPTION: Create default IRQ handlers ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CreateIrqHandlers Proc near mov eax,SEG data mov ds,eax mov ebx,OFFSET global_int_arr mov ecx,64 xor dl,dl create_irq_loop: mov ax,ds:[ebx].gi_ioapic_sel or ax,ax jz create_irq_next ; push ecx mov cx,1 xor al,al mov ds:[bx].gi_prio,al AllocateInts mov ds:[bx].gi_int_num,al pop ecx ; push ds push ebx ; push eax mov ds:[ebx].gi_long_ads,0 ; mov ax,create_long_irq_nr IsValidOsGate jc create_irq32 ; mov al,dl CreateLongIrq mov ds:[ebx].gi_long_ads,esi pop eax ; push eax xor bl,bl SetupLongIntGate create_irq32: mov al,dl call CreateIsaIrq pop eax ; xor bl,bl SetupIntGate mov ax,ds ; pop ebx pop ds mov ds:[ebx].gi_handler_sel,ax create_irq_next: add ebx,16 inc dl loop create_irq_loop ; ret CreateIrqHandlers Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ProcessApicTable ; ; DESCRIPTION: Define basic APIC vars ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ProcessApicTable Proc near mov eax,SEG data mov ds,eax call GetApicTable ; mov edi,OFFSET apic_entries movzx ecx,es:act_size sub ecx,OFFSET apic_entries - OFFSET apic_phys init_apic_loop: mov al,es:[edi].apic_type cmp al,2 jne init_apic_next ; mov al,es:[edi].ao_bus or al,al jnz init_apic_next ; mov al,es:[edi].ao_source cmp al,16 jae init_apic_next ; mov eax,es:[edi].ao_int cmp eax,80h jae init_apic_next ; mov ebx,eax shl ebx,4 add ebx,OFFSET global_int_arr ; mov ax,es:[edi].ao_flags test al,1 jz init_apic_redir_pol_ok ; test al,2 jz init_apic_redir_pol_high init_apic_redir_pol_low: or [ebx].gi_trigger_mode,20h jmp init_apic_redir_pol_ok init_apic_redir_pol_high: and [ebx].gi_trigger_mode,NOT 20h init_apic_redir_pol_ok: test al,4 jz init_apic_next ; test al,8 jz init_apic_redir_edge init_apic_redir_level: or [ebx].gi_trigger_mode,80h jmp init_apic_next init_apic_redir_edge: and [ebx].gi_trigger_mode,7Fh init_apic_next: movzx eax,es:[edi].apic_len add edi,eax sub ecx,eax ja init_apic_loop ret ProcessApicTable Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: DisablePic ; ; DESCRIPTION: Disable legacy PIC ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DisablePic Proc near push edx ; cli mov al,0FFh out 21h,al jmp short $+2 out 0A1h,al jmp short $+2 ; xor edx,edx mov al,0Bh out 0A0h,al jmp short $+2 in al,0A0h mov dh,al daiSlaveLoop: or al,al jz daiSlaveOk ; mov al,20h out 0A0h,al jmp short $+2 mov al,0Bh out 0A0h,al jmp short $+2 in al,0A0h jmp daiSlaveLoop daiSlaveOk: mov al,0Bh out 20h,al jmp short $+2 in al,20h mov dl,al daiMasterLoop: or al,al jz daiMasterOk ; mov al,20h out 20h,al jmp short $+2 mov al,0Bh out 20h,al jmp short $+2 in al,20h jmp daiMasterLoop daiMasterOk: pop edx ret DisablePic Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: Init ; ; DESCRIPTION: Init apic mp module ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; public init_apic init_apic PROC near push ds push es pushad ; mov eax,SEG data mov ds,eax mov ds:ioapic_spinlock,0 ; mov al,34h out TIMER_CONTROL,al jmp short $+2 mov al,0 out TIMER0,al jmp short $+2 out TIMER0,al jmp short $+2 ; mov eax,cs mov ds,eax mov es,eax ; mov esi,OFFSET get_ioapic_state mov edi,OFFSET get_ioapic_state_name xor cl,cl mov ax,get_ioapic_state_nr RegisterOsGate ; mov esi,OFFSET send_eoi mov edi,OFFSET send_eoi_name xor cl,cl mov ax,send_eoi_nr RegisterOsGate ; mov esi,OFFSET notify_irq mov edi,OFFSET notify_irq_name xor cl,cl mov ax,notify_irq_nr RegisterOsGate ; mov esi,OFFSET setup_irq_detect mov edi,OFFSET setup_irq_detect_name xor cl,cl mov ax,setup_irq_detect_nr RegisterOsGate ; mov esi,OFFSET poll_irq_detect mov edi,OFFSET poll_irq_detect_name xor cl,cl mov ax,poll_irq_detect_nr RegisterOsGate ; mov esi,OFFSET disable_all_irq mov edi,OFFSET disable_all_irq_name xor cl,cl mov ax,disable_all_irq_nr RegisterOsGate ; mov esi,OFFSET force_level_irq mov edi,OFFSET force_level_irq_name xor cl,cl mov ax,force_level_irq_nr RegisterOsGate ; mov esi,OFFSET request_irq_handler mov edi,OFFSET request_irq_handler_name xor cl,cl mov ax,request_irq_handler_nr RegisterOsGate ; call DisablePic call SetupInts call InitIoApic call CreateIrqHandlers call ProcessApicTable call SetupLocalApic call EnableDetect ; popad pop es pop ds ret init_apic ENDP code ENDS END