
tmp_page_tab      equ 0x01000000

align 4
proc mem_test
           mov eax, cr0
           or eax, (CR0_CD+CR0_NW);disable caching
           mov cr0, eax
           wbinvd                 ;invalidate cache

           xor     edi, edi
           mov ebx, 'TEST'
@@:
           add edi, 0x400000
           xchg ebx, dword [edi]
           cmp dword [edi], 'TEST'
           xchg ebx, dword [edi]
           je @b

           and eax, not (CR0_CD+CR0_NW)
           mov cr0, eax
           mov eax, edi
           ret
endp

align 4
proc init_memEx
           xor eax, eax
           mov edi, sys_pgdir
           mov ecx, 2048
           rep stosd

           bt [cpu_caps], CAPS_PSE
           jnc .no_PSE

           mov ebx, cr4
           or ebx, CR4_PSE
           mov eax, PG_LARGE+PG_SW
           bt [cpu_caps], CAPS_PGE
           jnc @F
           or eax, PG_GLOBAL
           or ebx, CR4_PGE

@@:
           mov cr4, ebx

           mov dword [sys_pgdir], eax
           add eax, 0x00400000
           mov dword [sys_pgdir+4], eax
           add eax, 0x00400000
           mov dword [sys_pgdir+8], eax
           add eax, 0x00400000
           mov dword [sys_pgdir+12], eax

           mov dword [sys_pgdir+0x600], sys_master_tab+PG_SW
           mov dword [sys_master_tab+0x600], sys_master_tab+PG_SW

           mov ecx, [pg_data.kernel_tables]
           sub ecx, 4
           mov eax, tmp_page_tab+PG_SW
           mov edi, sys_pgdir+16
           mov esi, sys_master_tab+16

           jmp .map_kernel_tabs
.no_PSE:
           mov eax, PG_SW
           mov esi, tmp_page_tab
           mov ecx, 4096/4      ;0x0 - 0x00FFFFFF
.map_low:
           mov [esi], eax
           add eax, 0x1000
           mov [esi+4], eax
           add eax, 0x1000
           mov [esi+8], eax
           add eax, 0x1000
           mov [esi+12], eax
           add eax, 0x1000
           add esi, 16
           dec ecx
           jnz .map_low            ;ядро

           mov ecx, [pg_data.kernel_tables]
           mov eax, tmp_page_tab+PG_SW
           mov edi, sys_pgdir
           mov esi, sys_master_tab

.map_kernel_tabs:

           mov [edi], eax
           mov [esi], eax
           add eax, 0x1000
           add edi, 4
           add esi, 4
           dec ecx
           jnz .map_kernel_tabs

           mov edi, tmp_page_tab
           bt [cpu_caps], CAPS_PSE
           jc @F
           add edi, 4096*4      ;skip low kernel memory
@@:
           mov ecx, [pg_data.kernel_tables]
           sub ecx, 4
           shl ecx, 10
           xor eax, eax
           cld
           rep stosd

           mov dword [sys_pgdir+0x600], sys_master_tab+PG_SW
           mov dword [sys_master_tab+0x600], sys_master_tab+PG_SW
           ret
endp

align 4
proc init_page_map
           mov edi, sys_pgmap
           mov ecx, 512/4
           xor eax,eax
           cld
           rep stosd

           not eax
           mov ecx, [pg_data.pagemap_size]
           sub ecx, 512
           shr ecx, 2
           rep stosd

           mov edi, sys_pgmap+512
           mov edx, [pg_data.pages_count]
           mov ecx, [pg_data.kernel_tables]
           bt [cpu_caps], CAPS_PSE
           jnc @f
           sub ecx, 4
@@:
           sub edx, 4096
           sub edx, ecx
           mov [pg_data.pages_free], edx

           xor eax, eax
           mov ebx, ecx
           shr ecx, 5
           rep stosd

           not eax
           mov ecx, ebx
           and ecx, 31
           shl eax, cl
           stosd

           mov [page_start], sys_pgmap+512
           mov ebx, sys_pgmap
           add ebx, [pg_data.pagemap_size]
           mov [page_end], ebx

           mov [pg_data.pg_mutex], 0

           ret
endp

align 4
proc alloc_page

           pushfd
           cli
           mov ebx, [page_start]
           mov ecx, [page_end]
.l1:
           bsf eax,[ebx];
           jnz .found
           add ebx,4
           cmp ebx, ecx
           jb .l1
           popfd
           xor eax,eax
           ret
.found:
           btr [ebx], eax
           mov [page_start],ebx
           sub ebx, sys_pgmap
           shl ebx, 3
           add eax,ebx
           shl eax, 12
           dec [pg_data.pages_free]
           popfd
           ret
endp

align 4
proc alloc_pages stdcall, count:dword
           pushfd
           cli
           mov eax, [count]
           add eax, 7
           shr eax, 3
           mov [count], eax
           cmp eax, [pg_data.pages_free]
           ja .fail

           mov ecx, [page_start]
           mov ebx, [page_end]
.find:
           mov edx, [count]
           mov edi, ecx

.match:
           cmp byte [ecx], 0xFF
           jne .next
           dec edx
           jz .ok
           inc ecx
           cmp ecx,ebx
           jb .match
.fail:     xor eax, eax
           popfd
           ret
.next:
           inc ecx
           cmp ecx, ebx
           jb .find
           popfd
           xor eax, eax
           ret
.ok:
           sub ecx, edi
           inc ecx
           mov esi, edi
           xor eax, eax
           rep stosb
           sub esi, sys_pgmap
           shl esi, 3+12
           mov eax, esi
           mov ebx, [count]
           shl ebx, 3
           sub [pg_data.pages_free], ebx
           popfd
           ret
endp

align 4
proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword
           mov eax, [phis_addr]
           and eax, not 0xFFF
           or eax, [flags]
           mov ebx, [lin_addr]
           shr ebx, 12
           mov [pages_tab+ebx*4], eax
           mov eax, [lin_addr]
           invlpg [eax]
           ret
endp

align 4
proc free_page
;arg:  eax  page address
           pushfd
           cli
           inc [pg_data.pages_free]
           shr eax, 12              ;page index
           mov ebx, sys_pgmap
           bts [ebx], eax           ;that's all!
           shr eax, 3
           and eax, not 3           ;dword offset from page_map
           add eax, ebx
           cmp [page_start], eax
           ja @f
           popfd
           ret
@@:
           mov [page_start], eax
           popfd
           ret
endp

align 4
proc map_page_table stdcall,page_dir:dword, lin_addr:dword, phis_addr:dword
           mov ebx, [lin_addr]
           shr ebx, 22
           mov eax, [phis_addr]
           and eax, not 0xFFF
           or eax, PG_UW          ;+PG_NOCACHE
           mov ecx, [page_dir]
           mov dword [ecx+ebx*4], eax
           mov dword [master_tab+ebx*4], eax
           mov eax, [lin_addr]
           shr eax, 10
           add eax, pages_tab
           invlpg [eax]
           ret
endp

align 4
proc init_LFB

           cmp dword [LFBAddress], -1
           jne @f

           stdcall kernel_alloc, 0x280000
           mov [LFBAddress], eax
           ret
@@:
           test [SCR_MODE],word 0100000000000000b
           jz @f
           call map_LFB
@@:
           ret
endp

align 4
proc map_LFB
           locals
             pg_count dd ?
           endl

           mov edi, [LFBSize]
           mov esi, [LFBAddress]
           shr edi, 12
           mov [pg_count], edi
           shr edi, 10

           bt [cpu_caps], CAPS_PSE
           jnc .map_page_tables
           mov ebx, esi
           or esi, PG_LARGE+PG_UW
           shr ebx, 20
           mov ecx, ebx
@@:
           mov [sys_pgdir+ebx], esi
           add ebx, 4
           add esi, 0x00400000
           dec edi
           jnz @B

           or dword [sys_pgdir+ecx], PG_GLOBAL
           mov eax, cr3       ;flush TLB
           mov cr3, eax
           ret

.map_page_tables:

@@:
           call alloc_page
           stdcall map_page_table,sys_pgdir, esi, eax
           add esi, 0x00400000
           dec edi
           jnz @B

           mov eax, [LFBAddress]
           mov esi, eax
           shr esi, 10
           add esi, pages_tab
           or eax, PG_UW
           mov ecx, [pg_count]
           shr ecx, 2
.map:
           mov [esi], eax
           add eax, 0x1000
           mov [esi+4], eax
           add eax, 0x1000
           mov [esi+8], eax
           add eax, 0x1000
           mov [esi+12], eax
           add eax, 0x1000
           add esi, 16
           sub ecx, 1
           jnz .map

           mov eax, cr3       ;flush TLB
           mov cr3, eax

           ret
endp

align 4
proc new_mem_resize stdcall, new_size:dword

           stdcall wait_mutex, pg_data.pg_mutex

           mov edi, [new_size]
           add edi,4095
           and edi,not 4095
           mov [new_size], edi

           mov edx,[CURRENT_TASK]
           shl edx,8
           cmp [PROC_BASE+APPDATA.heap_base+edx],0
           jne .exit

           mov esi, [PROC_BASE+APPDATA.mem_size+edx]
           add esi, 4095
           and esi, not 4095

           cmp edi, esi
           jae .expand

           shr edi, 12
           shr esi, 12
@@:
           mov eax, [pages_tab+0x00181000+edi*4]
           test eax, 1
           jz .next
           mov dword [pages_tab+0x00181000+edi*4], 2
           mov ebx, edi
           shl ebx, 12
           invlpg [ebx+std_application_base_address]
           call free_page

.next:     add edi, 1
           cmp edi, esi
           jb @B

.update_size:

           mov ebx, [new_size]
           mov    [PROC_BASE+0x8c+edx],ebx

;search threads and update
;application memory size infomation
           mov    ecx,[PROC_BASE+0xb8+edx]
           mov    eax,2

.search_threads:
;eax = current slot
;ebx = new memory size
;ecx = page directory
           cmp    eax,[TASK_COUNT]
           jg     .search_threads_end
           mov    edx,eax
           shl    edx,5
           cmp    word [CURRENT_TASK+edx+0xa],9 ;if slot empty?
           jz     .search_threads_next
           shl    edx,3
           cmp    [PROC_BASE+edx+0xb8],ecx     ;if it is our thread?
           jnz    .search_threads_next
           mov    [PROC_BASE+edx+0x8c],ebx     ;update memory size
.search_threads_next:
           inc    eax
           jmp    .search_threads
.search_threads_end:
           xor eax, eax
           dec [pg_data.pg_mutex]
           ret

.expand:
           add edi, new_app_base
           add esi, new_app_base

           push esi
           push edi

           add edi, 0x3FFFFF
           and edi, not(0x3FFFFF)
           add esi, 0x3FFFFF
           and esi, not(0x3FFFFF)

           cmp esi, edi
           jae .grow

           xchg esi, edi

           mov eax, cr3
           stdcall map_page,[tmp_task_pdir],eax,dword PG_SW+PG_NOCACHE

@@:
           call alloc_page
           test eax, eax
           jz .exit

           stdcall map_page_table,[tmp_task_pdir], edi, eax

           push edi
           shr edi, 10
           add edi, pages_tab
           mov ecx, 1024
           xor eax, eax
           cld
           rep stosd
           pop edi

           add edi, 0x00400000
           cmp edi, esi
           jb @B

           stdcall map_page,[tmp_task_pdir],dword 0,dword PG_UNMAP
.grow:
           pop edi
           pop esi
@@:
           call alloc_page
           test eax, eax
           jz .exit
           stdcall map_page,esi,eax,dword PG_UW

           push edi
           mov edi, esi
           xor eax, eax
           mov ecx, 1024
           cld
           rep stosd
           pop edi

           add esi, 0x1000
           cmp esi, edi
           jna @B

           jmp .update_size
.exit:
           xor eax, eax
           inc eax
           dec [pg_data.pg_mutex]
           ret
endp

align 4
proc get_pg_addr stdcall, lin_addr:dword
           mov ebx, [lin_addr]
           shr ebx, 12
           mov eax, [pages_tab+ebx*4]
           and eax, 0xFFFFF000
           ret
endp

align 16
proc page_fault_handler
           pushad

           mov ebp, esp
           mov eax, cr2
           push eax
           push ds

           mov ax, 0x10
           mov ds, ax

           mov ebx, [ebp-4]

           cmp ebx, 0xe0000000
           jae .lfb_addr

           cmp ebx, 0x60400000
           jae .user_space

           cmp ebx, 0x60000000
           jae .tab_space

           jmp .kernel_space

.user_space:
           inc [pg_data.pages_faults]

           shr ebx, 12
           mov ecx, ebx
           shr ecx, 10
           mov edx, [master_tab+ecx*4]
           test edx, 1
           jz .fail

           mov eax, [pages_tab+ebx*4]
           test eax, 2
           jz .fail

           call alloc_page
           and eax, eax
           jz .exit

           stdcall map_page,[ebp-4],eax,dword PG_UW

           mov esi, [ebp-4]
           and esi, 0xFFFFF000
           mov ecx, 1024
           xor eax, eax
@@:
           mov [esi], eax
           add esi, 4
           dec ecx
           jnz @B
.exit:
           pop ds
           mov esp, ebp
           popad
           add esp, 4
           iretd
.fail:
           pop ds
           mov esp, ebp
           popad
           add esp, 4

           save_ring3_context     ;debugger support

           mov bl, 14
           jmp exc_c
           iretd

.kernel_space:
           shr ebx, 12
           mov eax, [pages_tab+ebx*4]
           shr ebx, 10
           mov eax, [master_tab+ebx*4]

           pop ds
           mov esp, ebp
           popad
           add esp, 4
           iretd

.old_addr:
           shr ebx, 12
;           mov eax, [pages_tab+ebx*4]
           shr ebx, 10
           mov eax, [master_tab+ebx*4]

           pop ds
           mov esp, ebp
           popad
           add esp, 4
           iretd

.lfb_addr:
           shr ebx, 22
           ;mov ecx, [sys_page_dir]
           mov eax, [master_tab+ebx*4]

           pop ds
           mov esp, ebp
           popad
           add esp, 4
           iretd

.tab_space:
           shr ebx, 12
;           mov eax, [pages_tab+ebx*4]
           shr ebx, 10
           ;mov ecx, [sys_page_dir]
           mov eax, [master_tab+ebx*4]

           pop ds
           mov esp, ebp
           popad
           add esp, 4
           iretd
endp

align 4
proc map_mem stdcall, lin_addr:dword,pdir:dword,\
                      ofs:dword,buf_size:dword
           mov eax, [buf_size]
           test eax, eax
           jz .exit

           mov eax, [pdir]
           and eax, 0xFFFFF000

           stdcall map_page,[ipc_pdir],eax,dword PG_UW
           mov ebx, [ofs]
           shr ebx, 22
           mov esi, [ipc_pdir]
           mov edi, [ipc_ptab]
           mov eax, [esi+ebx*4]
           and eax, 0xFFFFF000
           test eax, eax
           jz .exit
           stdcall map_page,edi,eax,dword PG_UW
;           inc ebx
;           add edi, 0x1000
;           mov eax, [esi+ebx*4]
;           test eax, eax
;           jz @f
;          and eax, 0xFFFFF000
;           stdcall map_page, edi, eax

@@:        mov edi, [lin_addr]
           and edi, 0xFFFFF000
           mov ecx, [buf_size]
           add ecx, 4095
           shr ecx, 12
           inc ecx

           mov edx, [ofs]
           shr edx, 12
           and edx, 0x3FF
           mov esi, [ipc_ptab]

.map:      mov eax, [esi+edx*4]
           and eax, 0xFFFFF000
           test eax, eax
           jz .exit
           stdcall map_page,edi,eax,dword PG_UW
           add edi, 0x1000
           inc edx
           dec ecx
           jnz .map

.exit:
           ret
endp

align 4
proc map_memEx stdcall, lin_addr:dword,pdir:dword,\
                        ofs:dword,buf_size:dword
           mov eax, [buf_size]
           test eax, eax
           jz .exit

           mov eax, [pdir]
           and eax, 0xFFFFF000

           stdcall map_page,[proc_mem_pdir],eax,dword PG_UW
           mov ebx, [ofs]
           shr ebx, 22
           mov esi, [proc_mem_pdir]
           mov edi, [proc_mem_tab]
           mov eax, [esi+ebx*4]
           and eax, 0xFFFFF000
           test eax, eax
           jz .exit
           stdcall map_page,edi,eax,dword PG_UW

@@:        mov edi, [lin_addr]
           and edi, 0xFFFFF000
           mov ecx, [buf_size]
           add ecx, 4095
           shr ecx, 12
           inc ecx

           mov edx, [ofs]
           shr edx, 12
           and edx, 0x3FF
           mov esi, [proc_mem_tab]

.map:      mov eax, [esi+edx*4]
;           and eax, 0xFFFFF000
;           test eax, eax
;           jz .exit
           stdcall map_page,edi,eax,dword PG_UW
           add edi, 0x1000
           inc edx
           dec ecx
           jnz .map
.exit:
           ret
endp




sys_IPC:
;input:
;  eax=1 - set ipc buffer area
;    ebx=address of buffer
;    ecx=size of buffer
;  eax=2 - send message
;    ebx=PID
;    ecx=address of message
;    edx=size of message

           cmp  eax,1
           jne @f
           call set_ipc_buff
           mov [esp+36], eax
           ret

@@:
           cmp eax, 2
           jne @f
           stdcall sys_ipc_send, ebx, ecx, edx
           mov [esp+36], eax
           ret

@@:
           xor eax, eax
           not eax
           mov [esp+36], eax
           ret

align 4
proc set_ipc_buff

           mov  eax,[CURRENT_TASK]
           shl  eax,8
           add  eax, PROC_BASE
           pushf
           cli
           mov  [eax+0xA0],ebx     ;set fields in extended information area
           mov  [eax+0xA4],ecx

           add ebx,  new_app_base
           add ecx, ebx
           add ecx, 4095
           and ecx, not 4095

.touch:    mov eax, [ebx]
           add ebx, 0x1000
           cmp ebx, ecx
           jna .touch

           popf
           xor eax, eax
           ret
endp

proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
           locals
             dst_slot   dd ?
             dst_offset dd ?
             buf_size   dd ?
           endl

           pushf
           cli

           mov  eax, [PID]
           call pid_to_slot
           test eax,eax
           jz   .no_pid

           mov [dst_slot], eax
           shl  eax,8
           mov  edi,[eax+PROC_BASE+0xa0]  ;is ipc area defined?
           test edi,edi
           jz   .no_ipc_area

           mov ebx, edi
           add edi, new_app_base
           and ebx, 0xFFF
           mov [dst_offset], ebx

           mov esi, [eax+PROC_BASE+0xa4]
           mov [buf_size], esi

           stdcall map_mem, [ipc_tmp], [PROC_BASE+eax+0xB8],\
                             edi, esi

           mov edi, [dst_offset]
           add edi, [ipc_tmp]
           cmp dword [edi], 0
           jnz  .ipc_blocked          ;if dword [buffer]<>0 - ipc blocked now
           mov ebx, dword [edi+4]
           mov edx, ebx
           add ebx, 8
           add ebx, [msg_size]
           cmp ebx, [buf_size]
           ja .buffer_overflow         ;esi<0 - not enough memory in buffer
           mov dword [edi+4], ebx
           mov eax,[TASK_BASE]
           mov eax, [eax+0x04]         ;eax - our PID
           mov edi, [dst_offset]
           add edi, [ipc_tmp]
           add edi, edx
           mov [edi], eax
           mov ecx, [msg_size]

           mov [edi+4], ecx
           add edi, 8
           mov esi, [msg_addr]
           add esi, new_app_base
           cld
           rep movsb

           mov ebx, [ipc_tmp]
           mov edx, ebx
           shr ebx, 12
           xor eax, eax
           mov [pages_tab+ebx*4], eax
           invlpg [edx]

           mov ebx, [ipc_pdir]
           mov edx, ebx
           shr ebx, 12
           xor eax, eax
           mov [pages_tab+ebx*4], eax
           invlpg [edx]

           mov ebx, [ipc_ptab]
           mov edx, ebx
           shr ebx, 12
           xor eax, eax
           mov [pages_tab+ebx*4], eax
           invlpg [edx]

           mov  eax, [dst_slot]
           shl eax, 8
           or   [eax+PROC_BASE+0xA8],dword 0x40
           cmp  dword [check_idle_semaphore],20
           jge  .ipc_no_cis

           mov  dword [check_idle_semaphore],5
.ipc_no_cis:
           popf
           xor eax, eax
           ret
.no_pid:
           popf
           mov  eax, 4
           ret
.no_ipc_area:
           popf
           xor eax, eax
           inc eax
           ret
.ipc_blocked:
           popf
           mov  eax, 2
           ret
.buffer_overflow:
           popf
           mov  eax, 3
           ret
endp

align 4
sysfn_meminfo:

           add ebx, new_app_base
           cmp ebx, new_app_base
           jb .fail

           mov eax, [pg_data.pages_count]
           mov [ebx], eax
           shl eax, 12
           mov [esp+36], eax
           mov ecx, [pg_data.pages_free]
           mov [ebx+4], ecx
           mov edx, [pg_data.pages_faults]
           mov [ebx+8], edx
           mov esi, [heap_size]
           mov [ebx+12], esi
           mov edi, [heap_free]
           mov [ebx+16], edi
           mov eax, [heap_blocks]
           mov [ebx+20], eax
           mov ecx, [free_blocks]
           mov [ebx+24], ecx
           ret
.fail:
           mov dword [esp+36], -1
           ret

align 4
new_services:

           cmp  eax,4
           jle  sys_sheduler

           cmp eax, 11
           jb .fail
           ja @f

           stdcall init_heap, ebx
           mov [esp+36], eax
           ret
@@:
           cmp eax, 12
           ja @f

           stdcall user_alloc, ebx
           mov [esp+36], eax
           ret
@@:
           cmp eax, 13
           ja @f

           stdcall user_free, ebx
           mov [esp+36], eax
           ret
@@:
           cmp eax, 14
           ja @f
           add ebx,new_app_base
           cmp ebx, new_app_base
           jb .fail
           stdcall get_notify, ebx
           ret
@@:
           cmp eax, 15
           ja @f
           mov ecx, [CURRENT_TASK]
           shl ecx, 8
           mov eax, [ecx+PROC_BASE+APPDATA.fpu_handler]
           mov [ecx+PROC_BASE+APPDATA.fpu_handler], ebx
           mov [esp+36], eax
           ret
@@:
           cmp eax, 16
           ja @f

           add ebx, new_app_base
           cmp ebx, new_app_base
           jb .fail
           stdcall get_service, ebx
           mov [esp+36], eax
           ret
@@:
           cmp eax, 17
           ja @f
           stdcall srv_handlerEx, ebx
           mov [esp+36], eax
           ret
@@:
           cmp eax, 18
           ja @f
           mov ecx, [CURRENT_TASK]
           shl ecx, 8
           mov eax, [ecx+PROC_BASE+APPDATA.sse_handler]
           mov [ecx+PROC_BASE+APPDATA.sse_handler], ebx
           mov [esp+36], eax
           ret

@@:
.fail:
           xor eax, eax
           mov [esp+36], eax
           ret


align 4
proc strncmp stdcall, str1:dword, str2:dword, count:dword

          mov ecx,[count]
          jecxz .end

          mov ebx,ecx

          mov edi,[str1]
          mov esi,edi
          xor eax,eax
          repne scasb
          neg ecx             ; cx = count - strlen
          add ecx,ebx         ; strlen + count - strlen

.okay:
          mov edi,esi
          mov esi,[str2]
          repe cmpsb
          mov al,[esi-1]
          xor ecx,ecx

          cmp al,[edi-1]
          ja .str2_big
          je .end

.str1_big:
          sub ecx,2

.str2_big:
          not ecx
.end:
          mov eax,ecx
          ret
endp

align 4
proc fpu_save
           clts
           mov ebx, [fpu_owner]
           shl ebx, 8
           mov eax, [ebx+PROC_BASE+0x10]
           mov ebx, [CURRENT_TASK]
           mov [fpu_owner], ebx

           bt [cpu_caps], CAPS_FXSR
           jnc .no_SSE

           fxsave [eax]
           ret
.no_SSE:
           fnsave [eax]
           ret
endp

align 4
proc fpu_restore
           mov ebx, [CURRENT_TASK]
           shl ebx, 8
           mov eax, [ebx+PROC_BASE+0x10]
           bt [cpu_caps], CAPS_FXSR
           jnc .no_SSE

           fxrstor [eax]
           ret
.no_SSE:
           frstor [eax]
           ret
endp

align 4
proc test_cpu
           locals
              cpu_type   dd ?
              cpu_id     dd ?
              cpu_Intel  dd ?
              cpu_AMD    dd ?
           endl

           mov [cpu_type], 0

           pushfd
           pop eax
           mov ecx, eax
           xor eax, 0x40000
           push eax
           popfd
           pushfd
           pop eax
           xor eax, ecx
           mov [cpu_type], CPU_386
           jz .end_cpu
           push ecx
           popfd

           mov [cpu_type], CPU_486
           mov eax, ecx
           xor eax, 0x200000
           push eax
           popfd
           pushfd
           pop eax
           xor eax, ecx
           je .end_cpu
           mov [cpu_id], 1

           xor eax, eax
           cpuid
           mov [cpu_vendor], ebx
           mov [cpu_vendor+4], edx
           mov [cpu_vendor+8], ecx
           cmp ebx, dword [intel_str]
           jne .check_AMD
           cmp edx, dword [intel_str+4]
           jne .check_AMD
           cmp ecx, dword [intel_str+8]
           jne .check_AMD
           mov [cpu_Intel], 1
           cmp eax, 1
           jl .end_cpuid
           mov eax, 1
           cpuid
           mov [cpu_sign], eax
           mov [cpu_info],  ebx
           mov [cpu_caps],  edx
           mov [cpu_caps+4],ecx

           shr eax, 8
           and eax, 0x0f
           mov [cpu_type], eax
           ret

.end_cpuid:
           mov eax, [cpu_type]
           ret

.check_AMD:
           cmp ebx, dword [AMD_str]
           jne .end_cpu
           cmp edx, dword [AMD_str+4]
           jne .end_cpu
           cmp ecx, dword [AMD_str+8]
           jne .end_cpu
           mov [cpu_AMD], 1
           cmp eax, 1
           jl .end_cpuid
           mov eax, 1
           cpuid
           mov [cpu_sign], eax
           mov [cpu_info],  ebx
           mov [cpu_caps],  edx
           mov [cpu_caps+4],ecx
           shr eax, 8
           and eax, 0x0f
           mov [cpu_type], eax
.end_cpu:
           mov eax, [cpu_type]
           ret
endp

MEM_WB     equ 6               ;write-back memory
MEM_WC     equ 1               ;write combined memory
MEM_UC     equ 0               ;uncached memory

align 4
proc init_mtrr

           cmp [0x2f0000+0x901c],byte 2
           je  .exit

           mov eax, cr0
           or eax, 0x60000000   ;disable caching
           mov cr0, eax
           wbinvd               ;invalidate cache

           mov ecx, 0x2FF
           rdmsr                ;
           push eax

           xor edx, edx
           xor eax, eax
           mov ecx, 0x2FF
           wrmsr                ;disable all MTRR

           stdcall set_mtrr, dword 0,dword 0,[MEM_AMOUNT],MEM_WB
           stdcall set_mtrr, dword 1,[LFBAddress],[LFBSize],MEM_WC
           xor edx, edx
           xor eax, eax
           mov ecx, 0x204
           mov ebx, 6
@@:
           wrmsr                ;disable unused MTRR
           inc ecx
           wrmsr
           inc ecx
           dec ebx
           jnz @b

           wbinvd               ;again invalidate

           pop eax
           or eax, 0x800        ;set default memtype to UC
           and al, 0xF0
           mov ecx, 0x2FF
           wrmsr                ;and enable MTRR

           mov eax, cr0
           and eax, not 0x60000000
           mov cr0, eax         ; enable caching
.exit:
           ret
endp

align 4
proc set_mtrr stdcall, reg:dword,base:dword,size:dword,mem_type:dword

           xor edx, edx
           mov eax, [base]
           or eax, [mem_type]
           mov ecx, [reg]
           lea ecx, [0x200+ecx*2]
           wrmsr

           mov ebx, [size]
           dec ebx
           mov eax, 0xFFFFFFFF
           mov edx, 0x0000000F
           sub eax, ebx
           sbb edx, 0
           or eax, 0x800
           inc ecx
           wrmsr
           ret
endp

align 4
proc stall stdcall, delay:dword
           push ecx
           push edx
           push ebx
           push eax

           mov eax, [delay]
           mul [stall_mcs]
           mov ebx, eax       ;low
           mov ecx, edx       ;high
           rdtsc
           add ebx, eax
           adc ecx,edx
@@:
           rdtsc
           sub eax, ebx
           sbb edx, ecx
           jb @B

           pop eax
           pop ebx
           pop edx
           pop ecx
           ret
endp

iglobal
align 4
  intel_str    db "GenuineIntel",0
  AMD_str      db "AuthenticAMD",0
endg

uglobal
align 16
  irq_tab           rd 16


  MEM_FreeSpace     rd 1

  ipc_tmp           rd 1
  ipc_pdir          rd 1
  ipc_ptab          rd 1

  proc_mem_map      rd 1
  proc_mem_pdir     rd 1
  proc_mem_tab      rd 1

  tmp_task_pdir     rd 1
  tmp_task_ptab     rd 1
  tmp_task_data     rd 1

  current_pdir      rd 1

  fpu_data          rd 1
  fdd_buff          rd 1

  stall_mcs         rd 1
;;CPUID information

  cpu_vendor        rd 3
  cpu_sign          rd 1
  cpu_info          rd 1

endg

uglobal
align 16
   dll_tab         rb 32*32
   srv_tab         rb 32*32
   dll_map         rd 1
   srv_map         rd 1

   mem_used_list   rd 1
   mem_block_list  rd 64
   mem_block_map   rb 512
   mem_block_arr   rd 1
   mem_block_start rd 1
   mem_block_end   rd 1
   mem_block_mask  rd 2
   heap_size       rd 1
   heap_free       rd 1
   heap_blocks     rd 1
   free_blocks     rd 1

   page_start      rd 1
   page_end        rd 1
   sys_page_map    rd 1
;   app_load        rd 1
endg


;     push eax
;     push edx
;     mov edx, 0x400   ;bocsh
;     mov al,0xff      ;bocsh
;     out dx, al       ;bocsh
;     pop edx
;     pop eax

