Subversion Repositories Kolibri OS

Rev

Rev 7126 | Rev 7132 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 7130 $
  9.  
  10.  
  11. MEM_WB     equ 6               ;write-back memory
  12. MEM_WC     equ 1               ;write combined memory
  13. MEM_UC     equ 0               ;uncached memory
  14.  
  15. align 4
  16. proc mem_test
  17. ; if we have BIOS with fn E820, skip the test
  18.         cmp     dword [BOOT_VARS-OS_BASE + BOOT_MEMMAP_BLOCK_CNT], 0
  19.         jnz     .ret
  20.  
  21.         mov     eax, cr0
  22.         and     eax, not (CR0_CD+CR0_NW)
  23.         or      eax, CR0_CD       ;disable caching
  24.         mov     cr0, eax
  25.         wbinvd                    ;invalidate cache
  26.  
  27.         xor     edi, edi
  28.         mov     ebx, 'TEST'
  29. @@:
  30.         add     edi, 0x100000
  31.         xchg    ebx, dword [edi]
  32.         cmp     dword [edi], 'TEST'
  33.         xchg    ebx, dword [edi]
  34.         je      @b
  35.  
  36.         and     eax, not (CR0_CD+CR0_NW) ;enable caching
  37.         mov     cr0, eax
  38.         inc     dword [BOOT_VARS-OS_BASE + BOOT_MEMMAP_BLOCK_CNT]
  39.         xor     eax, eax
  40.         mov     [BOOT_VARS-OS_BASE + BOOT_MEMMAP_BLOCKS + e820entry.addr.lo], eax
  41.         mov     [BOOT_VARS-OS_BASE + BOOT_MEMMAP_BLOCKS + e820entry.addr.hi], eax
  42.         mov     [BOOT_VARS-OS_BASE + BOOT_MEMMAP_BLOCKS + e820entry.size.lo], edi
  43.         mov     [BOOT_VARS-OS_BASE + BOOT_MEMMAP_BLOCKS + e820entry.size.hi], eax
  44.         inc     eax
  45.         mov     [BOOT_VARS-OS_BASE + BOOT_MEMMAP_BLOCKS + e820entry.type], eax
  46. .ret:
  47.         ret
  48. endp
  49.  
  50. align 4
  51. proc init_mem
  52. ; calculate maximum allocatable address and number of allocatable pages
  53.         mov     edi, BOOT_VARS-OS_BASE + BOOT_MEMMAP_BLOCKS
  54.         mov     ecx, [edi-4]
  55.         xor     esi, esi; esi will hold total amount of memory
  56.         xor     edx, edx; edx will hold maximum allocatable address
  57. .calcmax:
  58. ; round all to pages
  59.         mov     eax, [edi]
  60.         cmp     [edi+16], byte 1
  61.         jne     .unusable
  62.  
  63.         test    eax, 0xFFF
  64.         jz      @f
  65.         neg     eax
  66.         and     eax, 0xFFF
  67.         add     [edi], eax
  68.         adc     dword [edi+4], 0
  69.         sub     [edi+8], eax
  70.         sbb     dword [edi+12], 0
  71.         jc      .unusable
  72. @@:
  73.         and     dword [edi+8], not 0xFFF
  74.         jz      .unusable
  75. ; ignore memory after 4 Gb
  76.         cmp     dword [edi+4], 0
  77.         jnz     .unusable
  78.         mov     eax, [edi]
  79.         cmp     dword [edi+12], 0
  80.         jnz     .overflow
  81.         add     eax, [edi+8]
  82.         jnc     @f
  83. .overflow:
  84.         mov     eax, 0xFFFFF000
  85. @@:
  86.         cmp     edx, eax
  87.         jae     @f
  88.         mov     edx, eax
  89. @@:
  90.         sub     eax, [edi]
  91.         mov     [edi+8], eax
  92.         add     esi, eax
  93.         jmp     .usable
  94. .unusable:
  95. ;        and     dword [edi+8], 0
  96. .usable:
  97.         add     edi, 20
  98.         loop    .calcmax
  99. .calculated:
  100.         mov     [MEM_AMOUNT-OS_BASE], esi
  101.         mov     [pg_data.mem_amount-OS_BASE], esi
  102.         shr     esi, 12
  103.         mov     [pg_data.pages_count-OS_BASE], esi
  104.  
  105.         shr     edx, 12
  106.         add     edx, 31
  107.         and     edx, not 31
  108.         shr     edx, 3
  109.         mov     [pg_data.pagemap_size-OS_BASE], edx
  110.  
  111.         add     edx, (sys_pgmap-OS_BASE)+4095
  112.         and     edx, not 4095
  113.         mov     [tmp_page_tabs], edx
  114.  
  115.         mov     edx, esi
  116.         and     edx, -1024
  117.         cmp     edx, (OS_BASE/4096)
  118.         jbe     @F
  119.         mov     edx, (OS_BASE/4096)
  120.         jmp     .set
  121. @@:
  122.         cmp     edx, (HEAP_BASE-OS_BASE+HEAP_MIN_SIZE)/4096
  123.         jae     .set
  124.         mov     edx, (HEAP_BASE-OS_BASE+HEAP_MIN_SIZE)/4096
  125. .set:
  126.         mov     [pg_data.kernel_pages-OS_BASE], edx
  127.         shr     edx, 10
  128.         mov     [pg_data.kernel_tables-OS_BASE], edx
  129.  
  130.         xor     eax, eax
  131.         mov     edi, sys_proc-OS_BASE
  132.         mov     ecx, 8192/4
  133.         cld
  134.         rep stosd
  135.  
  136.         mov     edx, (sys_proc-OS_BASE+PROC.pdt_0)+ 0x800; (OS_BASE shr 20)
  137.         bt      [cpu_caps-OS_BASE], CAPS_PSE
  138.         jnc     .no_PSE
  139.  
  140.         mov     ebx, cr4
  141.         or      ebx, CR4_PSE
  142.         mov     eax, PDE_LARGE+PG_SWR
  143.         mov     cr4, ebx
  144.         dec     [pg_data.kernel_tables-OS_BASE]
  145.  
  146.         mov     [edx], eax
  147.         add     edx, 4
  148.  
  149.         mov     edi, [tmp_page_tabs]
  150.         jmp     .map_kernel_heap        ; new kernel fits to the first 4Mb - nothing to do with ".map_low"
  151. .no_PSE:
  152.         mov     eax, PG_SWR
  153.         mov     ecx, [tmp_page_tabs]
  154.         shr     ecx, 12
  155. .map_low:
  156.         mov     edi, [tmp_page_tabs]
  157. @@:                                   ;
  158.         stosd
  159.         add     eax, 0x1000
  160.         dec     ecx
  161.         jnz     @B
  162.  
  163. .map_kernel_heap:
  164.         mov     ecx, [pg_data.kernel_tables-OS_BASE]
  165.         shl     ecx, 10
  166.         xor     eax, eax
  167.         rep stosd
  168.  
  169.         mov     ecx, [pg_data.kernel_tables-OS_BASE]
  170.         mov     eax, [tmp_page_tabs]
  171.         or      eax, PG_SWR
  172.         mov     edi, edx
  173.  
  174. .map_kernel_tabs:
  175.         stosd
  176.         add     eax, 0x1000
  177.         dec     ecx
  178.         jnz     .map_kernel_tabs
  179.  
  180.         mov     dword [sys_proc-OS_BASE+PROC.pdt_0+(page_tabs shr 20)], sys_proc+PROC.pdt_0+PG_SWR-OS_BASE
  181.  
  182.         mov     edi, (sys_proc+PROC.pdt_0-OS_BASE)
  183.         lea     esi, [edi+(OS_BASE shr 20)]
  184.         movsd
  185.         movsd
  186.         ret
  187. endp
  188.  
  189. align 4
  190. proc init_page_map
  191. ; mark all memory as unavailable
  192.         mov     edi, sys_pgmap-OS_BASE
  193.         mov     ecx, [pg_data.pagemap_size-OS_BASE]
  194.         shr     ecx, 2
  195.         xor     eax, eax
  196.         cld
  197.         rep stosd
  198.  
  199. ; scan through memory map and mark free areas as available
  200.         mov     ebx, BOOT_VARS-OS_BASE + BOOT_MEMMAP_BLOCKS
  201.         mov     edx, [ebx-4]
  202. .scanmap:
  203.         cmp     [ebx+16], byte 1
  204.         jne     .next
  205.  
  206.         mov     ecx, [ebx+8]
  207.         shr     ecx, 12; ecx = number of pages
  208.         jz      .next
  209.         mov     edi, [ebx]
  210.         shr     edi, 12; edi = first page
  211.         mov     eax, edi
  212.         shr     edi, 5
  213.         shl     edi, 2
  214.         add     edi, sys_pgmap-OS_BASE
  215.         and     eax, 31
  216.         jz      .startok
  217.         add     ecx, eax
  218.         sub     ecx, 32
  219.         jbe     .onedword
  220.         push    ecx
  221.         mov     ecx, eax
  222.         or      eax, -1
  223.         shl     eax, cl
  224.         or      [edi], eax
  225.         add     edi, 4
  226.         pop     ecx
  227. .startok:
  228.         push    ecx
  229.         shr     ecx, 5
  230.         or      eax, -1
  231.         rep stosd
  232.         pop     ecx
  233.         and     ecx, 31
  234.         neg     eax
  235.         shl     eax, cl
  236.         dec     eax
  237.         or      [edi], eax
  238.         jmp     .next
  239. .onedword:
  240.         add     ecx, 32
  241.         sub     ecx, eax
  242. @@:
  243.         bts     [edi], eax
  244.         inc     eax
  245.         loop    @b
  246. .next:
  247.         add     ebx, 20
  248.         dec     edx
  249.         jnz     .scanmap
  250.  
  251. ; mark kernel memory as allocated (unavailable)
  252.         mov     ecx, [tmp_page_tabs]
  253.         mov     edx, [pg_data.pages_count-OS_BASE]
  254.         shr     ecx, 12
  255.         add     ecx, [pg_data.kernel_tables-OS_BASE]
  256.         sub     edx, ecx
  257.         mov     [pg_data.pages_free-OS_BASE], edx
  258.  
  259.         mov     edi, sys_pgmap-OS_BASE
  260.         mov     ebx, ecx
  261.         shr     ecx, 5
  262.         xor     eax, eax
  263.         rep stosd
  264.  
  265.         not     eax
  266.         mov     ecx, ebx
  267.         and     ecx, 31
  268.         shl     eax, cl
  269.         and     [edi], eax
  270.         add     edi, OS_BASE
  271.         mov     [page_start-OS_BASE], edi;
  272.  
  273.         mov     ebx, sys_pgmap
  274.         add     ebx, [pg_data.pagemap_size-OS_BASE]
  275.         mov     [page_end-OS_BASE], ebx
  276.  
  277.         ret
  278. endp
  279.  
  280. align 4
  281.  
  282. init_BIOS32:
  283.         mov     edi, 0xE0000
  284. .pcibios_nxt:
  285.         cmp     dword[edi], '_32_'; "magic" word
  286.         je      .BIOS32_found
  287. .pcibios_nxt2:
  288.         add     edi, 0x10
  289.         cmp     edi, 0xFFFF0
  290.         je      .BIOS32_not_found
  291.         jmp     .pcibios_nxt
  292. .BIOS32_found:                  ; magic word found, check control summ
  293.  
  294.         movzx   ecx, byte[edi + 9]
  295.         shl     ecx, 4
  296.         mov     esi, edi
  297.         xor     eax, eax
  298.         cld      ; paranoia
  299. @@:
  300.         lodsb
  301.         add     ah, al
  302.         loop    @b
  303.         jnz     .pcibios_nxt2; control summ must be zero
  304.     ; BIOS32 service found !
  305.         mov     ebp, [edi + 4]
  306.         mov     [bios32_entry], ebp
  307.     ; check PCI BIOS present
  308.         mov     eax, '$PCI'
  309.         xor     ebx, ebx
  310.         push    cs  ; special for 'ret far' from  BIOS
  311.         call    ebp
  312.         test    al, al
  313.         jnz     .PCI_BIOS32_not_found
  314.  
  315.  ; здесь создаются дискрипторы для PCI BIOS
  316.  
  317.         add     ebx, OS_BASE
  318.         dec     ecx
  319.         mov     [(pci_code_32-OS_BASE)], cx   ;limit 0-15
  320.         mov     [(pci_data_32-OS_BASE)], cx   ;limit 0-15
  321.  
  322.         mov     [(pci_code_32-OS_BASE)+2], bx ;base  0-15
  323.         mov     [(pci_data_32-OS_BASE)+2], bx ;base  0-15
  324.  
  325.         shr     ebx, 16
  326.         mov     [(pci_code_32-OS_BASE)+4], bl ;base  16-23
  327.         mov     [(pci_data_32-OS_BASE)+4], bl ;base  16-23
  328.  
  329.         shr     ecx, 16
  330.         and     cl, 0x0F
  331.         mov     ch, bh
  332.         add     cx, D32
  333.         mov     [(pci_code_32-OS_BASE)+6], cx ;lim   16-19 &
  334.         mov     [(pci_data_32-OS_BASE)+6], cx ;base  24-31
  335.  
  336.         mov     [(pci_bios_entry-OS_BASE)], edx
  337.          ; jmp .end
  338. .PCI_BIOS32_not_found:
  339.         ; здесь должна заполнятся pci_emu_dat
  340. .BIOS32_not_found:
  341. .end:
  342.         ret
  343.  
  344. align 4
  345. proc test_cpu
  346.            locals
  347.               cpu_type   dd ?
  348.            endl
  349.  
  350.         xor     eax, eax
  351.         mov     [cpu_type], eax
  352.         mov     [cpu_caps-OS_BASE], eax
  353.         mov     [cpu_caps+4-OS_BASE], eax
  354.         mov     [cpu_phys_addr_width-OS_BASE], 32
  355.  
  356.         pushfd
  357.         pop     eax
  358.         mov     ecx, eax
  359.         xor     eax, EFLAGS_AC
  360.         push    eax
  361.         popfd
  362.         pushfd
  363.         pop     eax
  364.         xor     eax, ecx
  365.         mov     [cpu_type], CPU_386
  366.         jz      .end_cpuid
  367.         push    ecx
  368.         popfd
  369.  
  370.         mov     [cpu_type], CPU_486
  371.         mov     eax, ecx
  372.         xor     eax, EFLAGS_ID
  373.         push    eax
  374.         popfd
  375.         pushfd
  376.         pop     eax
  377.         xor     eax, ecx
  378.         je      .end_cpuid
  379.  
  380.         xor     eax, eax
  381.         cpuid
  382.  
  383.         mov     [cpu_vendor-OS_BASE], ebx
  384.         mov     [cpu_vendor+4-OS_BASE], edx
  385.         mov     [cpu_vendor+8-OS_BASE], ecx
  386.  
  387.         cmp     eax, 1
  388.         jl      .end_cpuid
  389.         mov     eax, 1
  390.         cpuid
  391.         mov     [cpu_sign-OS_BASE], eax
  392.         mov     [cpu_info-OS_BASE], ebx
  393.         mov     [cpu_caps-OS_BASE], edx
  394.         mov     [cpu_caps+4-OS_BASE], ecx
  395.  
  396.         bt      edx, CAPS_PAE
  397.         jnc     @f
  398.         mov     [cpu_phys_addr_width-OS_BASE], 36
  399. @@:
  400.         mov     eax, 0x80000000
  401.         cpuid
  402.         cmp     eax, 0x80000008
  403.         jb      @f
  404.         mov     eax, 0x80000008
  405.         cpuid
  406.         mov     [cpu_phys_addr_width-OS_BASE], al
  407. @@:
  408.  
  409.         mov     eax, [cpu_sign-OS_BASE]
  410.         shr     eax, 8
  411.         and     eax, 0x0f
  412.         ret
  413. .end_cpuid:
  414.         mov     eax, [cpu_type]
  415.         ret
  416. endp
  417.  
  418. iglobal
  419. align 4
  420. acpi_lapic_base   dd 0xfee00000   ; default local apic base
  421. endg
  422.  
  423. uglobal
  424. align 4
  425. acpi_rsdp         rd 1
  426. acpi_rsdt         rd 1
  427. acpi_madt         rd 1
  428.  
  429. acpi_dev_data     rd 1
  430. acpi_dev_size     rd 1
  431.  
  432. acpi_rsdt_base    rd 1
  433. acpi_fadt_base    rd 1
  434. acpi_dsdt_base    rd 1
  435. acpi_dsdt_size    rd 1
  436. acpi_madt_base    rd 1
  437. acpi_ioapic_base  rd 1
  438. acpi_hpet_base    rd 1
  439. hpet_base         rd 1
  440. hpet_period       rd 1
  441. hpet_timers       rd 1
  442. hpet_tsc_start    rd 2
  443. cpu_count         rd 1
  444. smpt              rd 16
  445. endg
  446.  
  447. ACPI_HI_RSDP_WINDOW_START  equ 0x000E0000
  448. ACPI_HI_RSDP_WINDOW_END    equ 0x00100000
  449. ACPI_RSDP_CHECKSUM_LENGTH  equ 20
  450.  
  451. ACPI_HPET_SIGN             equ 'HPET'
  452. ACPI_MADT_SIGN             equ 'APIC'
  453. ACPI_FADT_SIGN             equ 'FACP'
  454.  
  455.  
  456. acpi_locate:
  457.         push    ebx
  458.         push    edi
  459.  
  460. if defined UEFI
  461.         ; UEFI loader knows where RSDP is
  462.         mov     ebx, [BOOT_ACPI_RSDP]
  463.         test    ebx, ebx
  464.         jz      .done
  465.         call    .check
  466. else
  467.         movzx   ebx, word [0x40E]
  468.         shl     ebx, 4
  469.         lea     ecx, [ebx+1024]
  470.         call    .check
  471.  
  472.         test    ebx, ebx
  473.         jz      @F
  474.         jmp     .done
  475.  
  476. @@:
  477.         mov     ebx, ACPI_HI_RSDP_WINDOW_START
  478.         mov     edi, ACPI_HI_RSDP_WINDOW_END
  479.         call    .check
  480. end if
  481. .done:
  482.         mov     eax, ebx
  483.         pop     edi
  484.         pop     ebx
  485.         ret
  486.  
  487. .check:
  488.         cmp     [ebx], dword 'RSD '
  489.         jne     .next
  490.         cmp     [ebx+4], dword 'PTR '
  491.         jne     .next
  492.  
  493.         mov     edx, ebx
  494.         mov     ecx, ACPI_RSDP_CHECKSUM_LENGTH
  495.         xor     eax, eax
  496. .sum:
  497.         add     al, [edx]
  498.         inc     edx
  499.         loop    .sum
  500.  
  501.         test    al, al
  502.         jnz     .next
  503.         ret
  504. .next:
  505.         add     ebx, 16
  506.         cmp     ebx, edi
  507.         jb      .check
  508.         xor     ebx, ebx
  509.         ret
  510.  
  511. align 4
  512. rsdt_find:           ;ecx= rsdt edx= SIG
  513.         push    ebx
  514.         push    esi
  515.  
  516.         lea     ebx, [ecx+36]
  517.         mov     esi, [ecx+4]
  518.         add     esi, ecx
  519. align 4
  520. .next:
  521.         mov     eax, [ebx]
  522.         cmp     [eax], edx
  523.         je      .done
  524.  
  525.         add     ebx, 4
  526.         cmp     ebx, esi
  527.         jb      .next
  528.  
  529.         xor     eax, eax
  530.         pop     esi
  531.         pop     ebx
  532.         ret
  533.  
  534. .done:
  535.         mov     eax, [ebx]
  536.         pop     esi
  537.         pop     ebx
  538.         ret
  539.  
  540. align 4
  541. check_acpi:
  542.  
  543.         call    acpi_locate
  544.         test    eax, eax
  545.         jz      .done
  546.  
  547.         mov     [acpi_rsdp-OS_BASE], eax
  548.         mov     ecx, [eax+16]
  549.         mov     edx, ACPI_FADT_SIGN
  550.         mov     [acpi_rsdt_base-OS_BASE], ecx
  551.         call    rsdt_find
  552.         mov     [acpi_fadt_base-OS_BASE], eax
  553.         test    eax, eax
  554.         jz      @f
  555.  
  556.         mov     eax, [eax+40]
  557.         mov     [acpi_dsdt_base-OS_BASE], eax
  558.         mov     eax, [eax+4]
  559.         mov     [acpi_dsdt_size-OS_BASE], eax
  560. @@:
  561.         mov     edx, ACPI_HPET_SIGN
  562.         mov     ecx, [acpi_rsdt_base-OS_BASE]
  563.         call    rsdt_find
  564.         test    eax, eax
  565.         jz      @F
  566.  
  567.         mov     [acpi_hpet_base-OS_BASE], eax
  568.         mov     eax, [eax+44]
  569.         mov     [hpet_base-OS_BASE], eax
  570. @@:
  571.         mov     edx, ACPI_MADT_SIGN
  572.         mov     ecx, [acpi_rsdt_base-OS_BASE]
  573.         call    rsdt_find
  574.         test    eax, eax
  575.         jz      .done
  576.  
  577.         mov     [acpi_madt_base-OS_BASE], eax
  578.         mov     ecx, [eax+36]
  579.         mov     [acpi_lapic_base-OS_BASE], ecx
  580.  
  581.         mov     edi, smpt-OS_BASE
  582.         mov     ebx, [ecx+0x20]
  583.         shr     ebx, 24              ; read APIC ID
  584.  
  585.         mov     [edi], ebx           ; bootstrap always first
  586.         inc     [cpu_count-OS_BASE]
  587.         add     edi, 4
  588.  
  589.         lea     edx, [eax+44]
  590.         mov     ecx, [eax+4]
  591.         add     ecx, eax
  592. .check:
  593.         mov     eax, [edx]
  594.         cmp     al, 0
  595.         jne     .io_apic
  596.  
  597.         shr     eax, 24              ; get APIC ID
  598.         cmp     eax, ebx             ; skip self
  599.         je      .next
  600.  
  601.         test    [edx+4], byte 1      ; is enabled ?
  602.         jz      .next
  603.  
  604.         cmp     [cpu_count-OS_BASE], 16
  605.         jae     .next
  606.  
  607.         stosd                        ; store APIC ID
  608.         inc     [cpu_count-OS_BASE]
  609. .next:
  610.         mov     eax, [edx]
  611.         movzx   eax, ah
  612.         add     edx, eax
  613.         cmp     edx, ecx
  614.         jb      .check
  615. .done:
  616.         ret
  617.  
  618. .io_apic:
  619.         cmp     al, 1
  620.         jne     .next
  621.  
  622.         mov     eax, [edx+4]
  623.         mov     [acpi_ioapic_base-OS_BASE], eax
  624.         jmp     .next
  625.  
  626. HPET_PERIOD             equ 0x0004
  627. HPET_CFG_ENABLE         equ 0x0001
  628. HPET_CFG                equ 0x0010
  629. HPET_COUNTER            equ 0x00f0
  630. HPET_T0_CFG             equ 0x0100
  631.  
  632. HPET_TN_LEVEL           equ 0x0002
  633. HPET_TN_ENABLE          equ 0x0004
  634. HPET_TN_FSB             equ 0x4000
  635.  
  636. align 4
  637. init_hpet:
  638.         mov     ebx, [hpet_base-OS_BASE]
  639.         test    ebx, ebx
  640.         jz      .done
  641.  
  642.         mov     eax, [ebx]
  643.         and     ah, 0x1F
  644.         inc     ah
  645.         movzx   eax, ah
  646.         mov     [hpet_timers-OS_BASE], eax
  647.         mov     ecx, eax
  648.  
  649.         mov     eax, [ebx+HPET_PERIOD]
  650.         xor     edx, edx
  651.         shld    edx, eax, 10
  652.         shl     eax, 10
  653.         mov     esi, 1000000
  654.         div     esi
  655.         mov     [hpet_period-OS_BASE], eax
  656.  
  657.         mov     esi, [ebx+HPET_CFG]
  658.         and     esi, not HPET_CFG_ENABLE
  659.         mov     [ebx+HPET_CFG], esi             ;stop main counter
  660.  
  661.         lea     edx, [ebx+HPET_T0_CFG]
  662. @@:
  663.         jcxz    @F
  664.         mov     eax, [edx]
  665.         and     eax, not (HPET_TN_ENABLE+HPET_TN_LEVEL+HPET_TN_FSB)
  666.         mov     [edx], eax
  667.         add     edx, 0x20
  668.         dec     ecx
  669.         jmp     @B
  670. @@:
  671.         mov     [ebx+HPET_COUNTER], ecx         ;reset main counter
  672.         mov     [ebx+HPET_COUNTER+4], ecx
  673.  
  674.         or      esi, HPET_CFG_ENABLE
  675.         mov     [ebx+HPET_CFG], esi             ;and start again
  676.  
  677. .done:
  678.         rdtsc
  679.         mov     [hpet_tsc_start-OS_BASE], eax
  680.         mov     [hpet_tsc_start+4-OS_BASE], edx
  681.  
  682.         ret
  683.  
  684.  
  685.  
  686.  
  687.