;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 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 ; ; MP.ASM ; Multiprocessing 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\proc.inc INCLUDE ..\os\irq.inc INCLUDE ..\acpi\acpi.inc INCLUDE ..\user.def INCLUDE ..\user.inc INCLUDE pci.inc ipause MACRO db 0F3h db 90h ENDM MP_FLAG_TASK = 1 ; PCI IRQs active low, edge triggered apic_struc STRUC apic_type DB ? apic_len DB ? apic_struc ENDS apic_processor_struc STRUC ap_base apic_struc <> ap_acpi_id DB ? ap_apic_id DB ? ap_flags DD ? apic_processor_struc ENDS apic_ioapic_struc STRUC aio_base apic_struc <> aio_apic_id DB ? aio_resv DB ? aio_phys DD ? aio_int_base DD ? apic_ioapic_struc ENDS apic_override_struc STRUC ao_base apic_struc <> ao_bus DB ? ao_source DB ? ao_int DD ? ao_flags DW ? apic_override_struc ENDS apic_table STRUC apic_base acpi_table <> apic_phys DD ? apic_flags DD ? apic_entries DB ? apic_table ENDS hpet_table STRUC hpet_base acpi_table <> hpett_event_block DD ? hpett_flags DD ? hpett_phys_base DD ?,? hpett_nr DB ? hpett_min_tics DW ? hpet_table ENDS ioapic_data_seg STRUC ioapic_regsel DB ? ioapic_resv DB 15 DUP(?) ioapic_window DD ? ioapic_data_seg ENDS global_int_struc STRUC gi_ioapic_sel DW ? gi_ioapic_id DB ? gi_int_num DB ? global_int_struc ENDS hpet_counter_struc STRUC hpetc_config DD ? hpetc_int_mask DD ? hpetc_compare DD ?,? hpetc_msi_data DD ? hpetc_msi_ads DD ? hpetc_resv DD ?,? hpet_counter_struc ENDS hpet_struc STRUC hpet_cap DD ? hpet_period DD ? hpet_resv1 DD ?,? hpet_config DD ?,?,?,? hpet_int_status DD ?,?,?,? hpet_resv2 DB 0C0h DUP(?) hpet_count DD ?,?,?,? hpet_counter_arr DB 32 * SIZE hpet_counter_struc DUP(?) hpet_struc ENDS data SEGMENT byte public 'DATA' mp_flags DW ? mp_processor_sign DD ? time_spinlock DW ? clock_tics DW ? system_time DD ?,? apic_tics DD ? apic_rest DW ? hpet_guard DD ? prev_hpet DD ? hpet_sel DW ? hpet_factor DD ? hpet_counters DW ? isa_redir_arr DD 16 DUP(?,?) ioapic_count DW ? ioapic_arr DW 16 DUP(?) global_int_arr DD 256 DUP(?) data ENDS IFDEF __WASM__ .686p .xmm2 ELSE .386p ENDIF code SEGMENT byte public use16 'CODE' irqmac MACRO nr irq&nr: push ds push es push fs pushad ; EnterInt push fs sti ; mov ax,irq_sys_sel mov es,ax mov bx,OFFSET irq_arr + nr * SIZE irq_struc mov ax,word ptr es:[bx+4].user_handler or ax,ax jz irq_default_error&nr ; mov ds,es:[bx].user_data xor eax,eax mov ax,cs push eax mov ax,OFFSET irq_handle_done&nr push eax push es:[bx+4].user_handler push es:[bx].user_handler xor ax,ax mov es,ax retf32 irq_default_error&nr: ; ; unmask IRQ here ; or es:bad_irqs, 1 SHL nr irq_handle_done&nr: cli ; mov ax,apic_mem_sel mov ds,ax xor eax,eax mov ds:APIC_EOI,eax pop fs LeaveInt ; popad pop fs pop es pop ds iretd ENDM msimac MACRO nr msi&nr: push ds push es push fs pushad ; EnterInt push fs sti ; mov ax,irq_sys_sel mov es,ax mov bx,OFFSET msi_arr + nr * SIZE irq_struc mov ax,word ptr es:[bx+4].user_handler or ax,ax jz msi_default_error&nr ; mov ds,es:[bx].user_data xor eax,eax mov ax,cs push eax mov ax,OFFSET msi_handle_done&nr push eax push es:[bx+4].user_handler push es:[bx].user_handler xor ax,ax mov es,ax retf32 msi_default_error&nr: msi_handle_done&nr: cli ; mov ax,apic_mem_sel mov ds,ax xor eax,eax mov ds:APIC_EOI,eax pop fs LeaveInt ; popad pop fs pop es pop ds iretd ENDM assume cs:code ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: Tables ; ; DESCRIPTION: GDT for protected mode initialization of AP ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; this code is loaded at 0000:0F80h table_start: gdt0: dw 0 dd 0 dw 0 gdt8: dw 28h-1 dd 92000F80h dw 0 gdt10: dw 0FFFFh dd 9A001400h dw 0 gdt18: dw 0FFFFh dd 92000000h dw 0 gdt20: dw 0FFFFh dd 92001800h dw 0 table_end: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: RealMode ; ; DESCRIPTION: Real mode AP processor init ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; this code is loaded at 0100:0000. It should contain no near jumps! real_start: cli mov al,0Fh out 70h,al jmp short $+2 ; xor al,al out 71h,al jmp short $+2 ; xor ax,ax mov ds,ax ; mov bx,0F88h lgdt fword ptr ds:[bx] ; mov eax,cr0 or al,1 mov cr0,eax ; db 0EAh dw 0 dw 10h real_end: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ProtMode ; ; DESCRIPTION: Unpaged, protected mode AP processor init ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; this code is loaded at 01400. It should contain no near jumps! prot_start: mov ax,18h mov ds,ax mov es,ax mov fs,ax mov gs,ax mov ss,ax mov sp,0F00h ; mov ax,20h mov es,ax mov eax,es:ap_cr3 mov cr3,eax ; db 66h lgdt fword ptr es:ap_gdt ; db 66h lidt fword ptr es:ap_idt ; mov dx,es:ap_ss ; mov eax,es:ap_cr0 mov cr0,eax ; db 0EAh dw OFFSET ApInit dw SEG code prot_end: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: Paging ; ; DESCRIPTION: Paging variables for AP initialization ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; this code is loaded at 01800h. The code is relative to GDT selector 20h page_struc STRUC ap_ss DW ? ap_cr0 DD ? ap_cr3 DD ? ap_cr4 DD ? ap_gdt DB 6 DUP(?) ap_idt DB 6 DUP(?) page_struc ENDS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ApInit ; ; DESCRIPTION: Paged entry-point for AP initialization ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ApInit: mov eax,es:ap_cr4 db 0Fh db 22h db 0E0h ; mov cr4,eax ; xor ax,ax mov ds,ax mov es,ax mov fs,ax mov gs,ax ; mov ss,dx mov sp,200h ; mov ax,SEG data mov ds,ax mov eax,12345678h mov ds:mp_processor_sign,eax cli ap_task_wait: mov ax,ds:mp_flags test ax,MP_FLAG_TASK jz ap_task_wait ; call SetupLocalApic ; mov ax,start_preempt_timer_nr IsValidOsGate jc ap_timer_combined ; StartPreemptTimer jmp ap_timer_done ap_timer_combined: StartSysPreemptTimer ap_timer_done: RunApCore stopl: jmp stopl ap_crash: StartCrashCore ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SetupLocalApic ; ; DESCRIPTION: Setup local APIC ; ; PARAMETERS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SetupLocalApic Proc near push es push eax push bx ; mov bx,apic_mem_sel mov es,bx ; 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 ; mov eax,0 mov es:APIC_TPR,eax ; pop bx pop eax pop es ret SetupLocalApic Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: DelayMs ; ; DESCRIPTION: Delay for Init/SIPI ; ; PARAMETERS: AX Delay in ms ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DelayMs Proc near push ds push es pushad ; mov dx,SEG data mov ds,dx movzx eax,ax mov ecx,1193 mul ecx ; mov ecx,ds:apic_tics shl ecx,16 mov cx,ds:apic_rest shl eax,16 mul ecx inc edx ; mov ax,apic_mem_sel mov es,ax mov es:APIC_INIT_COUNT,edx dmLoop: mov eax,es:APIC_CURR_COUNT or eax,eax jnz dmLoop ; popad pop es pop ds ret DelayMs Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: GetId ; ; DESCRIPTION: Get own ID ; ; RETURNS: EDX Apic ID ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_id_name DB 'Get Apic ID',0 get_id Proc far push ds push ax ; mov ax,apic_mem_sel mov ds,ax mov edx,ds:APIC_ID shr edx,24 ; pop ax pop ds retf32 get_id 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 ax,apic_mem_sel mov ds,ax xor eax,eax mov ds:APIC_EOI,eax ; pop eax pop ds retf32 send_eoi Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SendNmi ; ; DESCRIPTION: Send NMI request ; ; PARAMETERS: FS Destination processor ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; send_nmi_name DB 'Send NMI', 0 send_nmi Proc far push ds push eax push edx ; mov edx,fs:ps_apic shl edx,24 mov ax,apic_mem_sel mov ds,ax mov ds:APIC_ICR+10h,edx ; mov eax,4400h mov ds:APIC_ICR,eax ; pop edx pop eax pop ds retf32 send_nmi Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: StartApCores ; ; DESCRIPTION: Start application cores ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; start_ap_cores_name DB 'Start Ap Cores',0 start_ap_cores Proc far push ds push ax ; mov ax,SEG data mov ds,ax or ds:mp_flags,MP_FLAG_TASK ; mov ax,1 call DelayMs ; pop ax pop ds retf32 start_ap_cores Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SendInt ; ; DESCRIPTION: Send int to processor ; ; PARAMETERS: FS Processor selector ; AL Int # ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; send_int_name DB 'Send Int',0 send_int Proc far pushf push ds push eax push ecx push edx ; cli shl edx,24 mov cx,apic_mem_sel mov ds,cx siLoop: mov ecx,ds:APIC_ICR test cx,1000h jz siDo ; ipause jmp siLoop siDo: mov ds:APIC_ICR+10h,edx ; mov ah,40h movzx eax,ax mov ds:APIC_ICR,eax ; pop edx pop ecx pop eax pop ds popf retf32 send_int Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: EnableIrq ; ; Description: Enable IRQ in IOAPIC controller ; ; PARAMETERS: AL irq nr ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; enable_irq Proc far push ds push eax push bx push edx ; movzx edx,al mov dh,0A9h cmp al,10h jae enable_irq_do ; mov bx,SEG data mov ds,bx movzx bx,al shl bx,3 mov edx,ds:[bx].isa_redir_arr or dh,9 sub dl,40h xchg al,dl enable_irq_do: add dl,40h ; mov bx,SEG data mov ds,bx movzx bx,al shl bx,2 add bx,OFFSET global_int_arr mov ax,ds:[bx].gi_ioapic_sel or ax,ax jz enable_irq_done ; push ax mov al,ds:[bx].gi_ioapic_id pop ds ; mov bl,10h add bl,al add bl,al ; mov ds:ioapic_regsel,bl mov ds:ioapic_window,edx ; inc bl mov ds:ioapic_regsel,bl mov edx,0FF000000h mov ds:ioapic_window,edx enable_irq_done: pop edx pop bx pop eax pop ds ret enable_irq Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: DisableIrq ; ; description: Disable IRQ in APIC controller ; ; PARAMETERS: AL irq nr ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; disable_irq Proc far push ds push eax push bx ; mov bx,SEG data mov ds,bx movzx bx,al shl bx,2 add bx,OFFSET global_int_arr mov ax,ds:[bx].gi_ioapic_sel or ax,ax jz disable_irq_done ; push ax mov al,ds:[bx].gi_ioapic_id pop ds ; mov bl,10h add bl,al add bl,al ; 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 disable_irq_done: pop bx pop eax pop ds ret disable_irq 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 bx push cx push si ; mov ax,apic_mem_sel mov ds,ax mov eax,10000h mov ds:APIC_TIMER,eax ; mov ax,SEG data mov ds,ax ; mov cx,ds:ioapic_count mov si,OFFSET ioapic_arr daiApicLoop: push ds push cx mov ds,ds:[si] ; mov cx,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 cx pop ds add si,2 loop daiApicLoop ; call SetupLocalApic ; mov ax,apic_mem_sel mov ds,ax mov eax,ds:APIC_ISR + 20h ; pop si pop cx pop bx pop ds retf32 disable_all_irq Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: EnableIrqDetect ; ; description: Enable IRQ detect in PIC controller ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; enable_irq_detect Proc far ret enable_irq_detect Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AllocateMsiInts ; ; DESCRIPTION: Allocate MSI interrupts ; ; PARAMETERS: CX Number of ints (1,2,4,8,16 or 32) ; ; RETURNS: EDX MSI address ; AX MSI data ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; allocate_msi_ints_name DB 'Allocate MSI Ints',0 allocate_msi_ints Proc far push ds push si ; mov dx,ds mov ax,irq_sys_sel mov ds,ax ; cmp cx,32 ja amiFailed ; cmp cx,16 jbe amiNot32 ami32: xor ax,ax mov edx,ds:msi_mask or edx,edx jnz ami32_1 ; mov edx,-1 mov ds:msi_mask,edx jmp amiOk ami32_1: mov ax,32 mov edx,ds:msi_mask+4 or edx,edx jnz amiFailed ; mov edx,-1 mov ds:msi_mask,edx jmp amiOk amiNot32: cmp cx,8 jbe amiNot16 ami16: xor ax,ax mov si,OFFSET msi_mask ami16Loop: mov dx,ds:[si] or dx,dx jnz ami16Next ; mov dx,-1 mov ds:[si],dx jmp amiOk ami16Next: add ax,16 add si,2 cmp ax,64 jne ami16Loop jmp amiFailed amiNot16: cmp cx,4 jbe amiNot8 ami8: xor ax,ax mov si,OFFSET msi_mask ami8Loop: mov dl,ds:[si] or dl,dl jnz ami8Next ; mov dl,-1 mov ds:[si],dl jmp amiOk ami8Next: add ax,8 inc si cmp ax,64 jne ami8Loop jmp amiFailed amiNot8: cmp cx,2 jbe amiNot4 ami4: xor ax,ax mov si,OFFSET msi_mask ami4Loop: mov dl,ds:[si] test dl,0Fh jnz ami4_1 ; mov dl,0Fh or ds:[si],dl jmp amiOk ami4_1: add ax,4 test dl,0F0h jnz ami4Next ; mov dl,0F0h or ds:[si],dl jmp amiOk ami4Next: add ax,4 inc si cmp ax,64 jne ami4Loop jmp amiFailed amiNot4: cmp cx,1 jbe ami1 ami2: xor ax,ax mov si,OFFSET msi_mask ami2Loop: mov dl,ds:[si] test dl,03h jnz ami2_1 ; mov dl,03h or ds:[si],dl jmp amiOk ami2_1: add ax,2 test dl,0Ch jnz ami2_2 ; mov dl,0Ch or ds:[si],dl jmp amiOk ami2_2: add ax,2 test dl,30h jnz ami2_3 ; mov dl,30h or ds:[si],dl jmp amiOk ami2_3: add ax,2 test dl,0C0h jnz ami2Next ; mov dl,0C0h or ds:[si],dl jmp amiOk ami2Next: add ax,2 inc si cmp ax,64 jne ami2Loop jmp amiFailed ami1: xor ax,ax mov si,OFFSET msi_mask ami1ByteLoop: mov dl,ds:[si] cmp dl,-1 je ami1NextByte ; mov dh,1 ami1BitLoop: shr dl,1 jc amiBitNext ; or ds:[si],dh jmp amiOk amiBitNext: shl dh,1 inc ax jmp ami1BitLoop ami1NextByte: add ax,8 inc si cmp ax,64 jne ami1ByteLoop jmp amiFailed amiOk: add al,0A0h mov ah,1 mov edx,0FEEFF000h clc jmp amiDone amiFailed: stc amiDone: pop si pop ds retf32 allocate_msi_ints Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: RequestMsiHandler ; ; DESCRIPTION: Request an MSI-based interrupt-handler ; ; PARAMETERS: DS Data passed to handler ; ES:EDI Handler address ; AX MSI data ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; request_msi_handler_name DB 'Request MSI Handler',0 request_msi_handler Proc far push ds push eax push dx push si ; push ds mov dx,irq_sys_sel mov ds,dx ; sub ax,0A0h xor ah,ah mov dx,SIZE irq_struc mul dx mov si,OFFSET msi_arr add si,ax pop dx ; EnterSection ds:[si].usage_section mov ds:[si].user_data,dx mov ds:[si].user_handler,edi mov word ptr ds:[si+4].user_handler,es ; pop si pop dx pop eax pop ds retf32 request_msi_handler Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: FreeMsiInt ; ; DESCRIPTION: Free a single MSI int vector ; ; PARAMETERS: AX MSI data ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; free_msi_int_name DB 'Free MSI Int',0 free_msi_int Proc far push ds push ax push si ; mov si,irq_sys_sel mov ds,si ; sub ax,0A0h xor ah,ah mov si,OFFSET msi_mask btc ds:[si],ax ; pop si pop ax pop ds retf32 free_msi_int Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: StartSysPreemptTimer ; ; DESCRIPTION: Start mixed system and preempt timer ; ; RETURNS: EAX Update tics ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; start_sys_preempt_timer_name DB 'Start Apic Sys Preempt Timer', 0 start_sys_preempt_timer Proc far push ds ; mov ax,apic_mem_sel mov ds,ax mov eax,83h mov ds:APIC_TIMER,eax xor eax,eax ; pop ds retf32 start_sys_preempt_timer Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ReloadSysPreemptTimer ; ; DESCRIPTION: Reload mixed system and preempt timer ; ; PARAMETERS: AX Reload tics ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; reload_sys_preempt_timer_name DB 'Reload Apic Sys Preempt Timer', 0 reload_sys_preempt_timer Proc far push ds push eax push ecx push edx ; mov cx,SEG data mov ds,cx ; mov ecx,ds:apic_tics shl ecx,16 mov cx,ds:apic_rest shl eax,16 mul ecx inc edx mov ax,apic_mem_sel mov ds,ax mov ds:APIC_INIT_COUNT,edx clc ; pop edx pop ecx pop eax pop ds retf32 reload_sys_preempt_timer Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: StartSysTimer ; ; DESCRIPTION: Start HPET sys timer ; ; RETURNS: EAX Update tics ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; start_hpet_timer_name DB 'Start HPET Timer', 0 start_hpet_timer Proc far push ds push es push bx push edx ; mov ax,SEG data mov ds,ax mov es,ds:hpet_sel mov bx,OFFSET hpet_counter_arr mov eax,es:[bx].hpetc_config test ax,8000h jnz start_hpet_msi start_hpet_iopic: ; mov eax,es:hpet_config ; or al,2 ; mov es:hpet_config,eax push bx ; mov bx,OFFSET global_int_arr + 4 * 2 mov ax,ds:[bx].gi_ioapic_sel ; push ax mov al,ds:[bx].gi_ioapic_id pop ds ; mov bl,10h add bl,al add bl,al ; mov edx,2982h mov ds:ioapic_regsel,bl mov ds:ioapic_window,edx ; inc bl mov ds:ioapic_regsel,bl mov edx,0FF000000h mov ds:ioapic_window,edx ; pop bx mov eax,es:[bx].hpetc_config ; and ax,NOT 7E0Ah or ax,506h mov es:[bx].hpetc_config,eax jmp start_hpet_done start_hpet_msi: mov ax,140h mov edx,0FEEFF000h mov es:[bx].hpetc_msi_data,eax mov es:[bx].hpetc_msi_ads,edx ; mov eax,es:[bx].hpetc_config and ax,NOT 0Ah or ax,4104h mov es:[bx].hpetc_config,eax start_hpet_done: xor eax,eax ; pop edx pop bx pop es pop ds retf32 start_hpet_timer Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ReloadSysTimer ; ; DESCRIPTION: Reload HPET timer ; ; PARAMETERS: AX Reload count ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; reload_hpet_timer_name DB 'Reload HPET Timer', 0 reload_hpet_timer Proc far push ds push eax push edx ; mov dx,SEG data mov ds,dx movzx eax,ax mov edx,31F5C4EDh mul edx div ds:hpet_factor inc eax ; mov ds,ds:hpet_sel mov ds:hpet_int_status,1 add eax,ds:hpet_count mov ds:hpet_counter_arr.hpetc_compare,eax mov eax,ds:hpet_counter_arr.hpetc_compare cmp eax,ds:hpet_count jg reload_hpet_ok ; stc jmp reload_hpet_done reload_hpet_ok: clc reload_hpet_done: pop edx pop eax pop ds retf32 reload_hpet_timer Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: StartPreemptionTimer ; ; DESCRIPTION: Start APIC timer ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; start_apic_preempt_timer_name DB 'Start Apic Preempt Timer', 0 start_apic_preempt_timer Proc far push ds mov ax,apic_mem_sel mov ds,ax mov eax,80h mov ds:APIC_TIMER,eax pop ds retf32 start_apic_preempt_timer Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ReloadPreemptionTimer ; ; DESCRIPTION: Reload APIC timer with preemption only ; ; PARAMETERS: AX Reload tics ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; reload_apic_preempt_timer_name DB 'Reload Apic Preempt Timer', 0 reload_apic_preempt_timer Proc far push ds push eax push ecx push edx ; mov cx,SEG data mov ds,cx ; mov ecx,ds:apic_tics shl ecx,16 mov cx,ds:apic_rest shl eax,16 mul ecx inc edx mov ax,apic_mem_sel mov ds,ax mov ds:APIC_INIT_COUNT,edx ; pop edx pop ecx pop eax pop ds retf32 reload_apic_preempt_timer Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: GetSystemTime ; ; DESCRIPTION: Read system time, PIT version ; ; RETURNS: EDX:EAX System time ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_pit_time_name DB 'Get System Time', 0 get_pit_time Proc far push ds ; mov ax,SEG data mov ds,ax gstSpinLock: mov ax,ds:time_spinlock or ax,ax je gstGet ; sti pause jmp gstSpinLock gstGet: cli inc ax xchg ax,ds:time_spinlock or ax,ax jne gstSpinLock ; mov al,0 out TIMER_CONTROL,al jmp short $+2 in al,TIMER0 mov ah,al jmp short $+2 in al,TIMER0 xchg al,ah mov dx,ax xchg ax,ds:clock_tics sub ax,dx movzx eax,ax add ds:system_time,eax adc ds:system_time+4,0 ; mov eax,ds:system_time mov edx,ds:system_time+4 ; mov ds:time_spinlock,0 sti pop ds retf32 get_pit_time Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: GetSystemTime ; ; DESCRIPTION: Read system time, HPET version ; ; RETURNS: EDX:EAX System time ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_hpet_time_name DB 'Get System Time', 0 get_hpet_time Proc far push ds push es push ecx ; mov ax,SEG data mov ds,ax ghtSpinLock: mov ax,ds:time_spinlock or ax,ax je ghtGet ; sti pause jmp ghtSpinLock ghtGet: cli inc ax xchg ax,ds:time_spinlock or ax,ax jne ghtSpinLock ; mov es,ds:hpet_sel mov eax,es:hpet_count mov edx,eax xchg edx,ds:prev_hpet sub eax,edx mul ds:hpet_factor add eax,ds:hpet_guard adc edx,0 ; mov ecx,31F5C4EDh div ecx mov ds:hpet_guard,edx add ds:system_time,eax adc ds:system_time+4,0 ; mov eax,ds:system_time mov edx,ds:system_time+4 ; mov ds:time_spinlock,0 sti ; pop ecx pop es pop ds retf32 get_hpet_time Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SetSystemTime ; ; DESCRIPTION: Set system time. Must not be called after tasking is ; started. ; ; PARAMETERS: EDX:EAX Binary time ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; set_system_time_name DB 'Set System Time',0 set_system_time PROC far push ds push bx mov bx,SEG data mov ds,bx mov ds:system_time,eax mov ds:system_time+4,edx pop bx pop ds retf32 set_system_time ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SetupPicInts ; ; DESCRIPTION: Setup IO-APIC IRQs ; ; PARAMETERS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; irqmac 1 irqmac 3 irqmac 4 irqmac 5 irqmac 6 irqmac 7 irqmac 8 irqmac 9 irqmac 10 irqmac 11 irqmac 12 irqmac 13 irqmac 14 irqmac 15 irqmac 16 irqmac 17 irqmac 18 irqmac 19 irqmac 20 irqmac 21 irqmac 22 irqmac 23 irqmac 24 irqmac 25 irqmac 26 irqmac 27 irqmac 28 irqmac 29 irqmac 30 irqmac 31 SetupPicInts Proc near push ds push es pushad ; mov ax,cs mov ds,ax mov es,ax ; xor bl,bl ; mov al,41h mov esi,OFFSET irq1 CreateIntGateSelector ; mov al,43h mov esi,OFFSET irq3 CreateIntGateSelector ; mov al,44h mov esi,OFFSET irq4 CreateIntGateSelector ; mov al,45h mov esi,OFFSET irq5 CreateIntGateSelector ; mov al,46h mov esi,OFFSET irq6 CreateIntGateSelector ; mov al,47h mov esi,OFFSET irq7 CreateIntGateSelector ; mov al,48h mov esi,OFFSET irq8 CreateIntGateSelector ; mov al,49h mov esi,OFFSET irq9 CreateIntGateSelector ; mov al,4Ah mov esi,OFFSET irq10 CreateIntGateSelector ; mov al,4Bh mov esi,OFFSET irq11 CreateIntGateSelector ; mov al,4Ch mov esi,OFFSET irq12 CreateIntGateSelector ; mov al,4Dh mov esi,OFFSET irq13 CreateIntGateSelector ; mov al,4Eh mov esi,OFFSET irq14 CreateIntGateSelector ; mov al,4Fh mov esi,OFFSET irq15 CreateIntGateSelector ; mov al,50h mov esi,OFFSET irq16 CreateIntGateSelector ; mov al,51h mov esi,OFFSET irq17 CreateIntGateSelector ; mov al,52h mov esi,OFFSET irq18 CreateIntGateSelector ; mov al,53h mov esi,OFFSET irq19 CreateIntGateSelector ; mov al,54h mov esi,OFFSET irq20 CreateIntGateSelector ; mov al,55h mov esi,OFFSET irq21 CreateIntGateSelector ; mov al,56h mov esi,OFFSET irq22 CreateIntGateSelector ; mov al,57h mov esi,OFFSET irq23 CreateIntGateSelector ; mov al,58h mov esi,OFFSET irq24 CreateIntGateSelector ; mov al,59h mov esi,OFFSET irq25 CreateIntGateSelector ; mov al,5Ah mov esi,OFFSET irq26 CreateIntGateSelector ; mov al,5Bh mov esi,OFFSET irq27 CreateIntGateSelector ; mov al,5Ch mov esi,OFFSET irq28 CreateIntGateSelector ; mov al,5Dh mov esi,OFFSET irq29 CreateIntGateSelector ; mov al,5Eh mov esi,OFFSET irq30 CreateIntGateSelector ; mov al,5Fh mov esi,OFFSET irq31 CreateIntGateSelector ; popad pop es pop ds ret SetupPicInts Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SetupMsiInts ; ; DESCRIPTION: Setup MSI IRQs ; ; PARAMETERS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; msimac 0 msimac 1 msimac 2 msimac 3 msimac 4 msimac 5 msimac 6 msimac 7 msimac 8 msimac 9 msimac 10 msimac 11 msimac 12 msimac 13 msimac 14 msimac 15 msimac 16 msimac 17 msimac 18 msimac 19 msimac 20 msimac 21 msimac 22 msimac 23 msimac 24 msimac 25 msimac 26 msimac 27 msimac 28 msimac 29 msimac 30 msimac 31 msimac 32 msimac 33 msimac 34 msimac 35 msimac 36 msimac 37 msimac 38 msimac 39 msimac 40 msimac 41 msimac 42 msimac 43 msimac 44 msimac 45 msimac 46 msimac 47 msimac 48 msimac 49 msimac 50 msimac 51 msimac 52 msimac 53 msimac 54 msimac 55 msimac 56 msimac 57 msimac 58 msimac 59 msimac 60 msimac 61 msimac 62 msimac 63 SetupMsiInts Proc near push ds push es pushad mov ax,cs mov ds,ax mov es,ax ; xor bl,bl ; mov al,0A0h mov esi,OFFSET msi0 CreateIntGateSelector ; mov al,0A1h mov esi,OFFSET msi1 CreateIntGateSelector ; mov al,0A2h mov esi,OFFSET msi2 CreateIntGateSelector ; mov al,0A3h mov esi,OFFSET msi3 CreateIntGateSelector ; mov al,0A4h mov esi,OFFSET msi4 CreateIntGateSelector ; mov al,0A5h mov esi,OFFSET msi5 CreateIntGateSelector ; mov al,0A6h mov esi,OFFSET msi6 CreateIntGateSelector ; mov al,0A7h mov esi,OFFSET msi7 CreateIntGateSelector ; mov al,0A8h mov esi,OFFSET msi8 CreateIntGateSelector ; mov al,0A9h mov esi,OFFSET msi9 CreateIntGateSelector ; mov al,0AAh mov esi,OFFSET msi10 CreateIntGateSelector ; mov al,0ABh mov esi,OFFSET msi11 CreateIntGateSelector ; mov al,0ACh mov esi,OFFSET msi12 CreateIntGateSelector ; mov al,0ADh mov esi,OFFSET msi13 CreateIntGateSelector ; mov al,0AEh mov esi,OFFSET msi14 CreateIntGateSelector ; mov al,0AFh mov esi,OFFSET msi15 CreateIntGateSelector ; mov al,0B0h mov esi,OFFSET msi16 CreateIntGateSelector ; mov al,0B1h mov esi,OFFSET msi17 CreateIntGateSelector ; mov al,0B2h mov esi,OFFSET msi18 CreateIntGateSelector ; mov al,0B3h mov esi,OFFSET msi19 CreateIntGateSelector ; mov al,0B4h mov esi,OFFSET msi20 CreateIntGateSelector ; mov al,0B5h mov esi,OFFSET msi21 CreateIntGateSelector ; mov al,0B6h mov esi,OFFSET msi22 CreateIntGateSelector ; mov al,0B7h mov esi,OFFSET msi23 CreateIntGateSelector ; mov al,0B8h mov esi,OFFSET msi24 CreateIntGateSelector ; mov al,0B9h mov esi,OFFSET msi25 CreateIntGateSelector ; mov al,0BAh mov esi,OFFSET msi26 CreateIntGateSelector ; mov al,0BBh mov esi,OFFSET msi27 CreateIntGateSelector ; mov al,0BCh mov esi,OFFSET msi28 CreateIntGateSelector ; mov al,0BDh mov esi,OFFSET msi29 CreateIntGateSelector ; mov al,0BEh mov esi,OFFSET msi30 CreateIntGateSelector ; mov al,0BFh mov esi,OFFSET msi31 CreateIntGateSelector ; mov al,0C0h mov esi,OFFSET msi32 CreateIntGateSelector ; mov al,0C1h mov esi,OFFSET msi33 CreateIntGateSelector ; mov al,0C2h mov esi,OFFSET msi34 CreateIntGateSelector ; mov al,0C3h mov esi,OFFSET msi35 CreateIntGateSelector ; mov al,0C4h mov esi,OFFSET msi36 CreateIntGateSelector ; mov al,0C5h mov esi,OFFSET msi37 CreateIntGateSelector ; mov al,0C6h mov esi,OFFSET msi38 CreateIntGateSelector ; mov al,0C7h mov esi,OFFSET msi39 CreateIntGateSelector ; mov al,0C8h mov esi,OFFSET msi40 CreateIntGateSelector ; mov al,0C9h mov esi,OFFSET msi41 CreateIntGateSelector ; mov al,0CAh mov esi,OFFSET msi42 CreateIntGateSelector ; mov al,0CBh mov esi,OFFSET msi43 CreateIntGateSelector ; mov al,0CCh mov esi,OFFSET msi44 CreateIntGateSelector ; mov al,0CDh mov esi,OFFSET msi45 CreateIntGateSelector ; mov al,0CEh mov esi,OFFSET msi46 CreateIntGateSelector ; mov al,0CFh mov esi,OFFSET msi47 CreateIntGateSelector ; mov al,0D0h mov esi,OFFSET msi48 CreateIntGateSelector ; mov al,0D1h mov esi,OFFSET msi49 CreateIntGateSelector ; mov al,0D2h mov esi,OFFSET msi50 CreateIntGateSelector ; mov al,0D3h mov esi,OFFSET msi51 CreateIntGateSelector ; mov al,0D4h mov esi,OFFSET msi52 CreateIntGateSelector ; mov al,0D5h mov esi,OFFSET msi53 CreateIntGateSelector ; mov al,0D6h mov esi,OFFSET msi54 CreateIntGateSelector ; mov al,0D7h mov esi,OFFSET msi55 CreateIntGateSelector ; mov al,0D8h mov esi,OFFSET msi56 CreateIntGateSelector ; mov al,0D9h mov esi,OFFSET msi57 CreateIntGateSelector ; mov al,0DAh mov esi,OFFSET msi58 CreateIntGateSelector ; mov al,0DBh mov esi,OFFSET msi59 CreateIntGateSelector ; mov al,0DCh mov esi,OFFSET msi60 CreateIntGateSelector ; mov al,0DDh mov esi,OFFSET msi61 CreateIntGateSelector ; mov al,0DEh mov esi,OFFSET msi62 CreateIntGateSelector ; mov al,0DFh mov esi,OFFSET msi63 CreateIntGateSelector ; popad pop es pop ds ret SetupMsiInts Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SpuriousInt ; ; DESCRIPTION: Spurious int ; ; PARAMETERS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; spurious_int: iretd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: TimerInt ; ; DESCRIPTION: Timer interrupt ; ; PARAMETERS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; timer_int: push ds push es push fs pushad ; mov ax,apic_mem_sel mov ds,ax xor eax,eax mov ds:APIC_EOI,eax ; TimerExpired ; popad pop fs pop es pop ds iretd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: HpetInt ; ; DESCRIPTION: HPET interrupt ; ; PARAMETERS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; hpet_int: push ds push es push fs pushad ; mov ax,SEG data mov ds,ax mov ds,ds:hpet_sel mov edx,ds:hpet_int_status mov ds:hpet_int_status,edx ; mov ax,apic_mem_sel mov ds,ax xor eax,eax mov ds:APIC_EOI,eax ; TimerExpired hpet_int_done: popad pop fs pop es pop ds iretd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: PreemptInt ; ; DESCRIPTION: Preempt interrupt ; ; PARAMETERS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; preempt_int: push ds push es push fs pushad ; mov ax,apic_mem_sel mov ds,ax xor eax,eax mov ds:APIC_EOI,eax ; PreemptExpired ; popad pop fs pop es pop ds iretd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: MixedInt ; ; DESCRIPTION: Mixed timer & preempt interrupt ; ; PARAMETERS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mixed_int: push ds push es push fs pushad ; mov ax,apic_mem_sel mov ds,ax xor eax,eax mov ds:APIC_EOI,eax ; PreemptTimerExpired ; popad pop fs pop es pop ds iretd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: tlb_flush_int ; ; DESCRIPTION: TLB flush int ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; tlb_flush_int: push ds push es push fs pushad ; mov ax,apic_mem_sel mov ds,ax xor eax,eax mov ds:APIC_EOI,eax ; FlushTlb ; popad pop fs pop es pop ds iretd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SetupInts ; ; DESCRIPTION: Setup ints ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ipi_tab: ; ; int # Entry ; pi0F DW 0Fh, OFFSET spurious_int pi40 DW 40h, OFFSET timer_int pi80 DW 80h, OFFSET preempt_int pi81 DW 81h, OFFSET tlb_flush_int pi82 DW 82h, OFFSET hpet_int pi83 DW 83h, OFFSET mixed_int DW 0FFFFh ; ; tabell offsets ; ipi_nr EQU 0 ipi_entry EQU 2 SetupInts Proc near push ds pushad ; mov ax,cs mov ds,ax xor bl,bl mov di,OFFSET ipi_tab ipiLoop: mov ax,cs:[di] cmp ax,0FFFFh jz ipiDone ; mov al,cs:[di].ipi_nr movzx esi, word ptr cs:[di].ipi_entry CreateIntGateSelector add di,4 jmp ipiLoop ipiDone: popad pop ds ret SetupInts Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SetupIrq ; ; DESCRIPTION: Setup IRQs to IOAPIC ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SetupIrq Proc near push ds pushad ; mov ax,irq_sys_sel mov ds,ax ; mov word ptr ds:irq_detect_proc,OFFSET enable_irq_detect mov word ptr ds:irq_detect_proc+2,cs ; mov cx,32 mov bx,OFFSET irq_arr xor eax,eax init_irq_loop: mov word ptr ds:[bx].irq_enable_proc,OFFSET enable_irq mov word ptr ds:[bx].irq_enable_proc+2,cs ; mov word ptr ds:[bx].irq_disable_proc,OFFSET disable_irq mov word ptr ds:[bx].irq_disable_proc+2,cs ; add bx,SIZE irq_struc loop init_irq_loop ; mov ds:msi_mask,0 mov ds:msi_mask+4,0 ; popad pop ds ret SetupIrq Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ProcessApicTable ; ; DESCRIPTION: Define basic APIC vars ; ; PARAMETERS: ES Apic table ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ProcessApicTable Proc near mov ax,SEG data mov ds,ax mov ds:ioapic_count,0 ; mov bx,OFFSET isa_redir_arr xor edx,edx mov eax,40h mov cx,16 init_apic_redir_loop: mov [bx],eax add bx,4 mov [bx],edx add bx,4 inc al loop init_apic_redir_loop ; mov bx,OFFSET isa_redir_arr + 2 * 8 mov eax,10000h mov [bx],eax ; push es mov ax,SEG data mov es,ax mov cx,256 xor eax,eax mov di,OFFSET global_int_arr rep stosd pop es ; mov eax,1000h AllocateBigLinear mov eax,es:apic_phys or ax,33h SetPhysicalPage mov bx,apic_mem_sel mov ecx,1000h CreateDataSelector16 ; mov di,OFFSET apic_entries mov cx,es:act_size sub cx,OFFSET apic_entries - OFFSET apic_phys init_apic_loop: mov al,es:[di].apic_type cmp al,1 je init_apic_ioapic ; cmp al,2 je init_apic_redir ; jmp init_apic_next init_apic_ioapic: push ecx mov eax,1000h AllocateBigLinear mov eax,es:[di].aio_phys or ax,33h SetPhysicalPage 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 cx pop ds ; mov bx,ds:ioapic_count add bx,bx mov ds:[bx].ioapic_arr,ax inc ds:ioapic_count ; mov ebx,es:[di].aio_int_base shl bx,2 add bx,OFFSET global_int_arr xor dl,dl init_ioapic_loop: mov ds:[bx].gi_ioapic_sel,ax mov ds:[bx].gi_ioapic_id,dl add bx,4 inc dl loop init_ioapic_loop ; pop ecx jmp init_apic_next init_apic_redir: mov al,es:[di].ao_bus or al,al jnz init_apic_next ; mov al,es:[di].ao_source cmp al,16 jae init_apic_next ; movzx bx,al shl bx,3 add bx,OFFSET isa_redir_arr ; mov eax,es:[di].ao_int cmp eax,80h jae init_apic_next ; add al,40h mov [bx],al ; mov ax,es:[di].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 word ptr [bx],2000h jmp init_apic_redir_pol_ok init_apic_redir_pol_high: and word ptr [bx], NOT 2000h 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 word ptr [bx],8000h jmp init_apic_next init_apic_redir_edge: and word ptr [bx],7FFFh init_apic_next: movzx ax,es:[di].apic_len add di,ax sub cx,ax ja init_apic_loop ret ProcessApicTable Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: InitApicTimer ; ; DESCRIPTION: Init APIC timer ; ; PARAMETERS: EAX Physical base of timer ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; read_tics MACRO mov al,0 out TIMER_CONTROL,al jmp short $+2 in al,TIMER0 mov ah,al jmp short $+2 in al,TIMER0 xchg al,ah ENDM InitApicTimer Proc near push ds push es pushad ; mov ax,SEG data mov ds,ax mov ax,apic_mem_sel mov es,ax init_tsc_start: xor cx,cx init_tsc_wait_start_high: read_tics test ax,8000h jnz init_tsc_wait_start_high_ok loop init_tsc_wait_start_high init_tsc_wait_start_high_ok: xor cx,cx init_tsc_wait_start_low: read_tics test ax,8000h jz init_tsc_wait_start_low_ok loop init_tsc_wait_start_low init_tsc_wait_start_low_ok: mov eax,-1 mov es:APIC_INIT_COUNT,eax init_apic_start_done: xor cx,cx init_tsc_wait_high: read_tics test ax,8000h jnz init_tsc_wait_high_ok loop init_tsc_wait_high init_tsc_wait_high_ok: xor cx,cx init_tsc_wait_low: read_tics test ax,8000h jz init_tsc_wait_low_ok loop init_tsc_wait_low init_tsc_wait_low_ok: mov eax,-1 sub eax,es:APIC_CURR_COUNT xor edx,edx mov ecx,8000h div ecx ; mov ds:apic_tics,eax mov ds:apic_rest,dx ; popad pop es pop ds ret InitApicTimer Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SendInit ; ; DESCRIPTION: Send init request ; ; PARAMETERS: EDX Destination ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SendInit Proc near push ds push eax push edx ; shl edx,24 mov ax,apic_mem_sel mov ds,ax mov ds:APIC_ICR+10h,edx ; mov eax,0C500h mov ds:APIC_ICR,eax ; mov ax,1 call DelayMs ; mov eax,08500h mov ds:APIC_ICR,eax ; mov ax,20 call DelayMs ; pop edx pop eax pop ds ret SendInit Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SendStartup ; ; DESCRIPTION: Send startup request ; ; PARAMETERS: EDX Destination ; AL Vector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SendStartup Proc near push ds push eax push ecx push edx ; shl edx,24 mov cx,apic_mem_sel mov ds,cx mov ds:APIC_ICR+10h,edx ; mov ah,46h movzx eax,ax mov ds:APIC_ICR,eax ; mov ax,1 call DelayMs ; pop edx pop ecx pop eax pop ds ret SendStartup Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: DoStartCore ; ; DESCRIPTION: Start a CPU core ; ; PARAMETERS: EDX APIC ID ; ; RETURNS: FS Processor sel ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DoStartCore Proc near push ds push es pushad ; mov ax,SEG data mov fs,ax ; mov ebp,edx mov eax,2000h AllocateBigLinear ; mov eax,63h SetPhysicalPage ; mov eax,1063h add edx,1000h SetPhysicalPage sub edx,1000h ; AllocateGdt mov ecx,2000h CreateDataSelector32 mov es,bx mov ax,cs mov ds,ax ; mov di,0F80h mov si,OFFSET table_start mov cx,OFFSET table_end - OFFSET table_start rep movsb ; mov di,1000h mov si,OFFSET real_start mov cx,OFFSET real_end - OFFSET real_start rep movsb ; mov di,1400h mov si,OFFSET prot_start mov cx,OFFSET prot_end - OFFSET prot_start rep movsb ; mov di,1800h mov eax,cr0 mov es:[di].ap_cr0,eax mov eax,cr3 mov es:[di].ap_cr3,eax ; db 0Fh db 20h db 0E0h ; mov eax,cr4 mov es:[di].ap_cr4,eax ; push cx push edx db 66h sidt fword ptr es:[di].ap_idt ; CreateCoreGdt dec cx mov word ptr es:[di].ap_gdt,cx mov dword ptr es:[di].ap_gdt+2,edx ; pop edx pop cx ; push es mov eax,200h AllocateSmallGlobalMem mov ax,es pop es mov es:[di].ap_ss,ax ; mov bx,467h mov ax,0 mov es:[bx],ax mov ax,100h mov es:[bx+2],ax ; mov al,0Fh out 70h,al jmp short $+2 ; mov al,0Ah out 71h,al jmp short $+2 ; mov fs:mp_processor_sign,0 ; xchg edx,ebp call SendInit ; mov eax,fs:mp_processor_sign cmp eax,12345678h je scOk ; mov al,1 call SendStartup mov cx,250 scLoop1: mov eax,fs:mp_processor_sign cmp eax,12345678h je scOk ; mov ax,1 call DelayMs loop scLoop1 ; mov al,1 call SendStartup ; mov cx,250 scLoop2: mov eax,fs:mp_processor_sign cmp eax,12345678h je scOk ; mov ax,1 call DelayMs loop scLoop2 ; xor ax,ax mov fs,ax stc jmp scDone scOk: push es mov edx,dword ptr es:[di].ap_gdt+2 CreateCore mov ax,es mov fs,ax pop es clc scDone: pushf ; mov al,0Fh out 70h,al jmp short $+2 ; xor al,al out 71h,al jmp short $+2 ; mov edx,ebp xor eax,eax add edx,1000h SetPhysicalPage sub edx,1000h ; SetPhysicalPage FreeMem ; popf popad pop es pop ds ret DoStartCore Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: StartupApCores ; ; DESCRIPTION: Startup application cores ; ; PARAMETERS: ES Apic table ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; StartupApCores Proc near mov di,OFFSET apic_entries mov cx,es:act_size sub cx,OFFSET apic_entries - OFFSET apic_phys xor bp,bp init_core_loop: mov al,es:[di].apic_type or al,al jnz init_core_next ; or bp,bp jnz init_ap_proc init_boot_proc: GetCore movzx edx,es:[di].ap_apic_id mov fs:ps_apic,edx ; mov al,es:[di].ap_acpi_id mov fs:ps_acpi,al inc bp jmp init_core_next init_ap_proc: mov eax,es:[di].ap_flags test al,1 jz init_core_next ; movzx edx,es:[di].ap_apic_id call DoStartCore jc init_core_next ; mov fs:ps_apic,edx mov al,es:[di].ap_acpi_id mov fs:ps_acpi,al ; inc bp cmp bp,4 je init_core_done init_core_next: movzx ax,es:[di].apic_len add di,ax sub cx,ax ja init_core_loop init_core_done: ret StartupApCores Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: apic_pr ; ; DESCRIPTION: APIC test thread ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; apic_name DB 'Apic Test',0 apic_pr: int 3 retf ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: init_apic_thread ; ; DESCRIPTION: Init apic threads ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; init_apic_thread PROC far push ds push es pusha ; mov ax,cs mov ds,ax mov es,ax ; mov si,OFFSET apic_pr mov di,OFFSET apic_name mov cx,stack0_size mov ax,4 CreateThread ; popa pop es pop ds retf32 init_apic_thread 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 ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; apic_tab DB 'APIC' hpet_tab DB 'HPET' init PROC far mov ax,SEG data mov ds,ax mov ds:mp_flags,0 mov ds:system_time,0 mov ds:system_time+4,0 mov ds:time_spinlock,0 mov ds:prev_hpet,0 mov ds:hpet_guard,0 ; mov al,34h out TIMER_CONTROL,al jmp short $+2 mov al,0 out TIMER0,al jmp short $+2 out TIMER0,al mov ds:clock_tics,0 jmp short $+2 ; mov eax,dword ptr cs:apic_tab GetAcpiTable jc init_apic_gates_ok ; push es mov ax,cs mov ds,ax mov es,ax ; mov esi,OFFSET start_ap_cores mov edi,OFFSET start_ap_cores_name xor cl,cl mov ax,start_ap_cores_nr RegisterOsGate ; mov esi,OFFSET send_int mov edi,OFFSET send_int_name xor cl,cl mov ax,send_int_nr RegisterOsGate ; mov esi,OFFSET get_id mov edi,OFFSET get_id_name xor cl,cl mov ax,get_apic_id_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 send_nmi mov edi,OFFSET send_nmi_name xor cl,cl mov ax,send_nmi_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 allocate_msi_ints mov edi,OFFSET allocate_msi_ints_name xor cl,cl mov ax,allocate_msi_ints_nr RegisterOsGate ; mov esi,OFFSET request_msi_handler mov edi,OFFSET request_msi_handler_name xor cl,cl mov ax,request_msi_handler_nr RegisterOsGate ; mov esi,OFFSET free_msi_int mov edi,OFFSET free_msi_int_name xor cl,cl mov ax,free_msi_int_nr RegisterOsGate ; mov si,OFFSET set_system_time mov di,OFFSET set_system_time_name xor cl,cl mov ax,set_system_time_nr RegisterOsGate ; mov esi,OFFSET start_sys_preempt_timer mov edi,OFFSET start_sys_preempt_timer_name xor cl,cl mov ax,start_sys_preempt_timer_nr RegisterOsGate ; mov esi,OFFSET reload_sys_preempt_timer mov edi,OFFSET reload_sys_preempt_timer_name xor cl,cl mov ax,reload_sys_preempt_timer_nr RegisterOsGate ; mov si,OFFSET get_pit_time mov di,OFFSET get_pit_time_name xor dx,dx mov ax,get_system_time_nr RegisterBimodalUserGate ; mov eax,dword ptr cs:hpet_tab GetAcpiTable jc init_hpet_done ; push es mov ax,cs mov ds,ax mov es,ax ; mov si,OFFSET get_hpet_time mov di,OFFSET get_hpet_time_name xor dx,dx mov ax,get_system_time_nr RegisterBimodalUserGate pop es ; mov ax,SEG data mov ds,ax ; mov eax,1000h AllocateBigLinear mov eax,es:hpett_phys_base or ax,33h SetPhysicalPage AllocateGdt mov ecx,1000h CreateDataSelector16 mov ds:hpet_sel,bx mov es,bx ; mov eax,es:hpet_config and al,NOT 2 mov es:hpet_config,eax ; mov eax,es:hpet_period mov ds:hpet_factor,eax ; mov eax,es:hpet_cap mov al,ah and ax,1Fh inc ax mov ds:hpet_counters,ax ; mov cx,ax mov bx,OFFSET hpet_counter_arr init_hpet_loop: mov eax,es:[bx].hpetc_config and ax,NOT 4004h mov es:[bx].hpetc_config,eax add bx,SIZE hpet_counter_struc loop init_hpet_loop ; mov eax,es:hpet_config and al,NOT 3 or al,1 mov es:hpet_config,eax ; mov bx,OFFSET hpet_counter_arr mov eax,es:[bx].hpetc_config test ax,8000h jz init_hpet_done ; mov ax,cs mov ds,ax mov es,ax ; mov esi,OFFSET start_apic_preempt_timer mov edi,OFFSET start_apic_preempt_timer_name xor cl,cl mov ax,start_preempt_timer_nr RegisterOsGate ; mov esi,OFFSET reload_apic_preempt_timer mov edi,OFFSET reload_apic_preempt_timer_name xor cl,cl mov ax,reload_preempt_timer_nr RegisterOsGate ; mov esi,OFFSET start_hpet_timer mov edi,OFFSET start_hpet_timer_name xor cl,cl mov ax,start_sys_timer_nr RegisterOsGate ; mov esi,OFFSET reload_hpet_timer mov edi,OFFSET reload_hpet_timer_name xor cl,cl mov ax,reload_sys_timer_nr RegisterOsGate init_hpet_done: pop es ; call DisablePic ; call SetupInts call SetupPicInts call SetupMsiInts call SetupIrq ; call ProcessApicTable call SetupLocalApic ; call InitApicTimer call StartupApCores ; mov ax,cs mov es,ax mov edi,OFFSET init_apic_thread HookInitTasking init_apic_gates_ok: ret init ENDP code ENDS END init