forked from KolibriOS/kolibrios
kolibri-process:
v86 works now, at least in VBox git-svn-id: svn://kolibrios.org@4993 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
c8deb6df88
commit
e72c474426
@ -5,7 +5,7 @@
|
|||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
$Revision: 4273 $
|
$Revision: 4437 $
|
||||||
|
|
||||||
; =============================================================================
|
; =============================================================================
|
||||||
; ================================= Constants =================================
|
; ================================= Constants =================================
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
$Revision: 4133 $
|
$Revision: 4465 $
|
||||||
|
|
||||||
; Read/write functions try to do large operations,
|
; Read/write functions try to do large operations,
|
||||||
; it is significantly faster than several small operations.
|
; it is significantly faster than several small operations.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
$Revision: 4273 $
|
$Revision: 4695 $
|
||||||
|
|
||||||
|
|
||||||
;**********************************************************
|
;**********************************************************
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
$Revision: 4420 $
|
$Revision: 4839 $
|
||||||
|
|
||||||
|
|
||||||
; Low-level driver for HDD access
|
; Low-level driver for HDD access
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
;
|
;
|
||||||
;**************************************************************************
|
;**************************************************************************
|
||||||
|
|
||||||
$Revision: 3742 $
|
$Revision: 4700 $
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
find_empty_slot_CD_cache:
|
find_empty_slot_CD_cache:
|
||||||
|
@ -94,6 +94,7 @@ __exports:
|
|||||||
load_cursor, 'LoadCursor', \ ;stdcall
|
load_cursor, 'LoadCursor', \ ;stdcall
|
||||||
\
|
\
|
||||||
get_curr_task, 'GetCurrentTask', \
|
get_curr_task, 'GetCurrentTask', \
|
||||||
|
change_task, 'ChangeTask', \
|
||||||
load_file, 'LoadFile', \ ;retval eax, ebx
|
load_file, 'LoadFile', \ ;retval eax, ebx
|
||||||
delay_ms, 'Sleep', \
|
delay_ms, 'Sleep', \
|
||||||
\
|
\
|
||||||
|
881
kernel/branches/kolibri-process/core/mtrr.inc
Normal file
881
kernel/branches/kolibri-process/core/mtrr.inc
Normal file
@ -0,0 +1,881 @@
|
|||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; ;;
|
||||||
|
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
|
||||||
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
|
;; ;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
$Revision: 4619 $
|
||||||
|
|
||||||
|
; Initializes MTRRs.
|
||||||
|
proc init_mtrr
|
||||||
|
|
||||||
|
cmp [BOOT_VARS+BOOT_MTRR], byte 2
|
||||||
|
je .exit
|
||||||
|
|
||||||
|
bt [cpu_caps], CAPS_MTRR
|
||||||
|
jnc .exit
|
||||||
|
|
||||||
|
call mtrr_reconfigure
|
||||||
|
stdcall set_mtrr, [LFBAddress], 0x1000000, MEM_WC
|
||||||
|
|
||||||
|
.exit:
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
|
||||||
|
; Helper procedure for mtrr_reconfigure and set_mtrr,
|
||||||
|
; called before changes in MTRRs.
|
||||||
|
proc mtrr_begin_change
|
||||||
|
mov eax, cr0
|
||||||
|
or eax, 0x60000000 ;disable caching
|
||||||
|
mov cr0, eax
|
||||||
|
wbinvd ;invalidate cache
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
|
||||||
|
; Helper procedure for mtrr_reconfigure and set_mtrr,
|
||||||
|
; called after changes in MTRRs.
|
||||||
|
proc mtrr_end_change
|
||||||
|
wbinvd ;again invalidate
|
||||||
|
mov eax, cr0
|
||||||
|
and eax, not 0x60000000
|
||||||
|
mov cr0, eax ; enable caching
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
|
||||||
|
; Some limits to number of structures located in the stack.
|
||||||
|
MAX_USEFUL_MTRRS = 16
|
||||||
|
MAX_RANGES = 16
|
||||||
|
|
||||||
|
; mtrr_reconfigure keeps a list of MEM_WB ranges.
|
||||||
|
; This structure describes one item in the list.
|
||||||
|
struct mtrr_range
|
||||||
|
next dd ? ; next item
|
||||||
|
start dq ? ; first byte
|
||||||
|
length dq ? ; length in bytes
|
||||||
|
ends
|
||||||
|
|
||||||
|
uglobal
|
||||||
|
align 4
|
||||||
|
num_variable_mtrrs dd 0 ; number of variable-range MTRRs
|
||||||
|
endg
|
||||||
|
|
||||||
|
; Helper procedure for MTRR initialization.
|
||||||
|
; Takes MTRR configured by BIOS and tries to recongifure them
|
||||||
|
; in order to allow non-UC data at top of 4G memory.
|
||||||
|
; Example: if low part of physical memory is 3.5G = 0xE0000000 bytes wide,
|
||||||
|
; BIOS can configure two MTRRs so that the first MTRR describes [0, 4G) as WB
|
||||||
|
; and the second MTRR describes [3.5G, 4G) as UC;
|
||||||
|
; WB+UC=UC, so the resulting memory map would be as needed,
|
||||||
|
; but in this configuration our attempts to map LFB at (say) 0xE8000000 as WC
|
||||||
|
; would be ignored, WB+UC+WC is still UC.
|
||||||
|
; So we must keep top of 4G memory not covered by MTRRs,
|
||||||
|
; using three WB MTRRs [0,2G) + [2G,3G) + [3G,3.5G),
|
||||||
|
; this gives the same memory map, but allows to add further entries.
|
||||||
|
; See mtrrtest.asm for detailed input/output from real hardware+BIOS.
|
||||||
|
proc mtrr_reconfigure
|
||||||
|
push ebp ; we're called from init_LFB, and it feels hurt when ebp is destroyed
|
||||||
|
; 1. Prepare local variables.
|
||||||
|
; 1a. Create list of MAX_RANGES free (aka not yet allocated) ranges.
|
||||||
|
xor eax, eax
|
||||||
|
lea ecx, [eax+MAX_RANGES]
|
||||||
|
.init_ranges:
|
||||||
|
sub esp, sizeof.mtrr_range - 4
|
||||||
|
push eax
|
||||||
|
mov eax, esp
|
||||||
|
dec ecx
|
||||||
|
jnz .init_ranges
|
||||||
|
mov eax, esp
|
||||||
|
; 1b. Fill individual local variables.
|
||||||
|
xor edx, edx
|
||||||
|
sub esp, MAX_USEFUL_MTRRS * 16 ; .mtrrs
|
||||||
|
push edx ; .mtrrs_end
|
||||||
|
push edx ; .num_used_mtrrs
|
||||||
|
push eax ; .first_free_range
|
||||||
|
push edx ; .first_range: no ranges yet
|
||||||
|
mov cl, [cpu_phys_addr_width]
|
||||||
|
or eax, -1
|
||||||
|
shl eax, cl ; note: this uses cl&31 = cl-32, not the entire cl
|
||||||
|
push eax ; .phys_reserved_mask
|
||||||
|
virtual at esp
|
||||||
|
.phys_reserved_mask dd ?
|
||||||
|
.first_range dd ?
|
||||||
|
.first_free_range dd ?
|
||||||
|
.num_used_mtrrs dd ?
|
||||||
|
.mtrrs_end dd ?
|
||||||
|
.mtrrs rq MAX_USEFUL_MTRRS * 2
|
||||||
|
.local_vars_size = $ - esp
|
||||||
|
end virtual
|
||||||
|
|
||||||
|
; 2. Get the number of variable-range MTRRs from MTRRCAP register.
|
||||||
|
; Abort if zero.
|
||||||
|
mov ecx, 0xFE
|
||||||
|
rdmsr
|
||||||
|
test al, al
|
||||||
|
jz .abort
|
||||||
|
mov byte [num_variable_mtrrs], al
|
||||||
|
; 3. Validate MTRR_DEF_TYPE register.
|
||||||
|
mov ecx, 0x2FF
|
||||||
|
rdmsr
|
||||||
|
; If BIOS has not initialized variable-range MTRRs, fallback to step 7.
|
||||||
|
test ah, 8
|
||||||
|
jz .fill_ranges_from_memory_map
|
||||||
|
; If the default memory type (not covered by MTRRs) is not UC,
|
||||||
|
; then probably BIOS did something strange, so it is better to exit immediately
|
||||||
|
; hoping for the best.
|
||||||
|
cmp al, MEM_UC
|
||||||
|
jnz .abort
|
||||||
|
; 4. Validate all variable-range MTRRs
|
||||||
|
; and copy configured MTRRs to the local array [.mtrrs].
|
||||||
|
; 4a. Prepare for the loop over existing variable-range MTRRs.
|
||||||
|
mov ecx, 0x200
|
||||||
|
lea edi, [.mtrrs]
|
||||||
|
.get_used_mtrrs_loop:
|
||||||
|
; 4b. For every MTRR, read PHYSBASEn and PHYSMASKn.
|
||||||
|
; In PHYSBASEn, clear upper bits and copy to ebp:ebx.
|
||||||
|
rdmsr
|
||||||
|
or edx, [.phys_reserved_mask]
|
||||||
|
xor edx, [.phys_reserved_mask]
|
||||||
|
mov ebp, edx
|
||||||
|
mov ebx, eax
|
||||||
|
inc ecx
|
||||||
|
; If PHYSMASKn is not active, ignore this MTRR.
|
||||||
|
rdmsr
|
||||||
|
inc ecx
|
||||||
|
test ah, 8
|
||||||
|
jz .get_used_mtrrs_next
|
||||||
|
; 4c. For every active MTRR, check that number of local entries is not too large.
|
||||||
|
inc [.num_used_mtrrs]
|
||||||
|
cmp [.num_used_mtrrs], MAX_USEFUL_MTRRS
|
||||||
|
ja .abort
|
||||||
|
; 4d. For every active MTRR, store PHYSBASEn with upper bits cleared.
|
||||||
|
; This contains the MTRR base and the memory type in low byte.
|
||||||
|
mov [edi], ebx
|
||||||
|
mov [edi+4], ebp
|
||||||
|
; 4e. For every active MTRR, check that the range is continuous:
|
||||||
|
; PHYSMASKn with upper bits set must be negated power of two, and
|
||||||
|
; low bits of PHYSBASEn must be zeroes:
|
||||||
|
; PHYSMASKn = 1...10...0,
|
||||||
|
; PHYSBASEn = x...x0...0,
|
||||||
|
; this defines a continuous range from x...x0...0 to x...x1...1,
|
||||||
|
; length = 10...0 = negated PHYSMASKn.
|
||||||
|
; Store length in the local array.
|
||||||
|
and eax, not 0xFFF
|
||||||
|
or edx, [.phys_reserved_mask]
|
||||||
|
mov dword [edi+8], 0
|
||||||
|
mov dword [edi+12], 0
|
||||||
|
sub [edi+8], eax
|
||||||
|
sbb [edi+12], edx
|
||||||
|
; (x and -x) is the maximum power of two that divides x.
|
||||||
|
; Condition for powers of two: (x and -x) equals x.
|
||||||
|
and eax, [edi+8]
|
||||||
|
and edx, [edi+12]
|
||||||
|
cmp eax, [edi+8]
|
||||||
|
jnz .abort
|
||||||
|
cmp edx, [edi+12]
|
||||||
|
jnz .abort
|
||||||
|
sub eax, 1
|
||||||
|
sbb edx, 0
|
||||||
|
and eax, not 0xFFF
|
||||||
|
and eax, ebx
|
||||||
|
jnz .abort
|
||||||
|
and edx, ebp
|
||||||
|
jnz .abort
|
||||||
|
; 4f. For every active MTRR, validate memory type: it must be either WB or UC.
|
||||||
|
add edi, 16
|
||||||
|
cmp bl, MEM_UC
|
||||||
|
jz .get_used_mtrrs_next
|
||||||
|
cmp bl, MEM_WB
|
||||||
|
jnz .abort
|
||||||
|
.get_used_mtrrs_next:
|
||||||
|
; 4g. Repeat the loop at 4b-4f for all [num_variable_mtrrs] entries.
|
||||||
|
mov eax, [num_variable_mtrrs]
|
||||||
|
lea eax, [0x200+eax*2]
|
||||||
|
cmp ecx, eax
|
||||||
|
jb .get_used_mtrrs_loop
|
||||||
|
; 4h. If no active MTRRs were detected, fallback to step 7.
|
||||||
|
cmp [.num_used_mtrrs], 0
|
||||||
|
jz .fill_ranges_from_memory_map
|
||||||
|
mov [.mtrrs_end], edi
|
||||||
|
; 5. Generate sorted list of ranges marked as WB.
|
||||||
|
; 5a. Prepare for the loop over configured MTRRs filled at step 4.
|
||||||
|
lea ecx, [.mtrrs]
|
||||||
|
.fill_wb_ranges:
|
||||||
|
; 5b. Ignore non-WB MTRRs.
|
||||||
|
mov ebx, [ecx]
|
||||||
|
cmp bl, MEM_WB
|
||||||
|
jnz .next_wb_range
|
||||||
|
mov ebp, [ecx+4]
|
||||||
|
and ebx, not 0xFFF ; clear memory type and reserved bits
|
||||||
|
; ebp:ebx = start of the range described by the current MTRR.
|
||||||
|
; 5c. Find the first existing range containing a point greater than ebp:ebx.
|
||||||
|
lea esi, [.first_range]
|
||||||
|
.find_range_wb:
|
||||||
|
; If there is no next range or start of the next range is greater than ebp:ebx,
|
||||||
|
; exit the loop to 5d.
|
||||||
|
mov edi, [esi]
|
||||||
|
test edi, edi
|
||||||
|
jz .found_place_wb
|
||||||
|
mov eax, ebx
|
||||||
|
mov edx, ebp
|
||||||
|
sub eax, dword [edi+mtrr_range.start]
|
||||||
|
sbb edx, dword [edi+mtrr_range.start+4]
|
||||||
|
jb .found_place_wb
|
||||||
|
; Otherwise, if end of the next range is greater than or equal to ebp:ebx,
|
||||||
|
; exit the loop to 5e.
|
||||||
|
mov esi, edi
|
||||||
|
sub eax, dword [edi+mtrr_range.length]
|
||||||
|
sbb edx, dword [edi+mtrr_range.length+4]
|
||||||
|
jb .expand_wb
|
||||||
|
or eax, edx
|
||||||
|
jnz .find_range_wb
|
||||||
|
jmp .expand_wb
|
||||||
|
.found_place_wb:
|
||||||
|
; 5d. ebp:ebx is not within any existing range.
|
||||||
|
; Insert a new range between esi and edi.
|
||||||
|
; (Later, during 5e, it can be merged with the following ranges.)
|
||||||
|
mov eax, [.first_free_range]
|
||||||
|
test eax, eax
|
||||||
|
jz .abort
|
||||||
|
mov [esi], eax
|
||||||
|
mov edx, [eax+mtrr_range.next]
|
||||||
|
mov [.first_free_range], edx
|
||||||
|
mov dword [eax+mtrr_range.start], ebx
|
||||||
|
mov dword [eax+mtrr_range.start+4], ebp
|
||||||
|
; Don't fill [eax+mtrr_range.next] and [eax+mtrr_range.length] yet,
|
||||||
|
; they will be calculated including merges at step 5e.
|
||||||
|
mov esi, edi
|
||||||
|
mov edi, eax
|
||||||
|
.expand_wb:
|
||||||
|
; 5e. The range at edi contains ebp:ebx, and esi points to the first range
|
||||||
|
; to be checked for merge: esi=edi if ebp:ebx was found in an existing range,
|
||||||
|
; esi is next after edi if a new range with ebp:ebx was created.
|
||||||
|
; Merge it with following ranges while start of the next range is not greater
|
||||||
|
; than the end of the new range.
|
||||||
|
add ebx, [ecx+8]
|
||||||
|
adc ebp, [ecx+12]
|
||||||
|
; ebp:ebx = end of the range described by the current MTRR.
|
||||||
|
.expand_wb_loop:
|
||||||
|
; If there is no next range or start of the next range is greater than ebp:ebx,
|
||||||
|
; exit the loop to 5g.
|
||||||
|
test esi, esi
|
||||||
|
jz .expand_wb_done
|
||||||
|
mov eax, ebx
|
||||||
|
mov edx, ebp
|
||||||
|
sub eax, dword [esi+mtrr_range.start]
|
||||||
|
sbb edx, dword [esi+mtrr_range.start+4]
|
||||||
|
jb .expand_wb_done
|
||||||
|
; Otherwise, if end of the next range is greater than or equal to ebp:ebx,
|
||||||
|
; exit the loop to 5f.
|
||||||
|
sub eax, dword [esi+mtrr_range.length]
|
||||||
|
sbb edx, dword [esi+mtrr_range.length+4]
|
||||||
|
jb .expand_wb_last
|
||||||
|
; Otherwise, the current range is completely within the new range.
|
||||||
|
; Free it and continue the loop.
|
||||||
|
mov edx, [esi+mtrr_range.next]
|
||||||
|
cmp esi, edi
|
||||||
|
jz @f
|
||||||
|
mov eax, [.first_free_range]
|
||||||
|
mov [esi+mtrr_range.next], eax
|
||||||
|
mov [.first_free_range], esi
|
||||||
|
@@:
|
||||||
|
mov esi, edx
|
||||||
|
jmp .expand_wb_loop
|
||||||
|
.expand_wb_last:
|
||||||
|
; 5f. Start of the new range is inside range described by esi,
|
||||||
|
; end of the new range is inside range described by edi.
|
||||||
|
; If esi is equal to edi, the new range is completely within
|
||||||
|
; an existing range, so proceed to the next range.
|
||||||
|
cmp esi, edi
|
||||||
|
jz .next_wb_range
|
||||||
|
; Otherwise, set end of interval at esi to end of interval at edi
|
||||||
|
; and free range described by edi.
|
||||||
|
mov ebx, dword [esi+mtrr_range.start]
|
||||||
|
mov ebp, dword [esi+mtrr_range.start+4]
|
||||||
|
add ebx, dword [esi+mtrr_range.length]
|
||||||
|
adc ebp, dword [esi+mtrr_range.length+4]
|
||||||
|
mov edx, [esi+mtrr_range.next]
|
||||||
|
mov eax, [.first_free_range]
|
||||||
|
mov [esi+mtrr_range.next], eax
|
||||||
|
mov [.first_free_range], esi
|
||||||
|
mov esi, edx
|
||||||
|
.expand_wb_done:
|
||||||
|
; 5g. We have found the next range (maybe 0) after merging and
|
||||||
|
; the new end of range (maybe ebp:ebx from the new range
|
||||||
|
; or end of another existing interval calculated at step 5f).
|
||||||
|
; Write them to range at edi.
|
||||||
|
mov [edi+mtrr_range.next], esi
|
||||||
|
sub ebx, dword [edi+mtrr_range.start]
|
||||||
|
sbb ebp, dword [edi+mtrr_range.start+4]
|
||||||
|
mov dword [edi+mtrr_range.length], ebx
|
||||||
|
mov dword [edi+mtrr_range.length+4], ebp
|
||||||
|
.next_wb_range:
|
||||||
|
; 5h. Continue the loop 5b-5g over all configured MTRRs.
|
||||||
|
add ecx, 16
|
||||||
|
cmp ecx, [.mtrrs_end]
|
||||||
|
jb .fill_wb_ranges
|
||||||
|
; 6. Exclude all ranges marked as UC.
|
||||||
|
; 6a. Prepare for the loop over configured MTRRs filled at step 4.
|
||||||
|
lea ecx, [.mtrrs]
|
||||||
|
.fill_uc_ranges:
|
||||||
|
; 6b. Ignore non-UC MTRRs.
|
||||||
|
mov ebx, [ecx]
|
||||||
|
cmp bl, MEM_UC
|
||||||
|
jnz .next_uc_range
|
||||||
|
mov ebp, [ecx+4]
|
||||||
|
and ebx, not 0xFFF ; clear memory type and reserved bits
|
||||||
|
; ebp:ebx = start of the range described by the current MTRR.
|
||||||
|
lea esi, [.first_range]
|
||||||
|
; 6c. Find the first existing range containing a point greater than ebp:ebx.
|
||||||
|
.find_range_uc:
|
||||||
|
; If there is no next range, ignore this MTRR,
|
||||||
|
; exit the loop and continue to next MTRR.
|
||||||
|
mov edi, [esi]
|
||||||
|
test edi, edi
|
||||||
|
jz .next_uc_range
|
||||||
|
; If start of the next range is greater than or equal to ebp:ebx,
|
||||||
|
; exit the loop to 6e.
|
||||||
|
mov eax, dword [edi+mtrr_range.start]
|
||||||
|
mov edx, dword [edi+mtrr_range.start+4]
|
||||||
|
sub eax, ebx
|
||||||
|
sbb edx, ebp
|
||||||
|
jnb .truncate_uc
|
||||||
|
; Otherwise, continue the loop if end of the next range is less than ebp:ebx,
|
||||||
|
; exit the loop to 6d otherwise.
|
||||||
|
mov esi, edi
|
||||||
|
add eax, dword [edi+mtrr_range.length]
|
||||||
|
adc edx, dword [edi+mtrr_range.length+4]
|
||||||
|
jnb .find_range_uc
|
||||||
|
; 6d. ebp:ebx is inside (or at end of) an existing range.
|
||||||
|
; Split the range. (The second range, maybe containing completely within UC-range,
|
||||||
|
; maybe of zero length, can be removed at step 6e, if needed.)
|
||||||
|
mov edi, [.first_free_range]
|
||||||
|
test edi, edi
|
||||||
|
jz .abort
|
||||||
|
mov dword [edi+mtrr_range.start], ebx
|
||||||
|
mov dword [edi+mtrr_range.start+4], ebp
|
||||||
|
mov dword [edi+mtrr_range.length], eax
|
||||||
|
mov dword [edi+mtrr_range.length+4], edx
|
||||||
|
mov eax, [edi+mtrr_range.next]
|
||||||
|
mov [.first_free_range], eax
|
||||||
|
mov eax, [esi+mtrr_range.next]
|
||||||
|
mov [edi+mtrr_range.next], eax
|
||||||
|
; don't change [esi+mtrr_range.next] yet, it will be filled at step 6e
|
||||||
|
mov eax, ebx
|
||||||
|
mov edx, ebp
|
||||||
|
sub eax, dword [esi+mtrr_range.start]
|
||||||
|
sbb edx, dword [esi+mtrr_range.start+4]
|
||||||
|
mov dword [esi+mtrr_range.length], eax
|
||||||
|
mov dword [esi+mtrr_range.length+4], edx
|
||||||
|
.truncate_uc:
|
||||||
|
; 6e. edi is the first range after ebp:ebx, check it and next ranges
|
||||||
|
; for intersection with the new range, truncate heads.
|
||||||
|
add ebx, [ecx+8]
|
||||||
|
adc ebp, [ecx+12]
|
||||||
|
; ebp:ebx = end of the range described by the current MTRR.
|
||||||
|
.truncate_uc_loop:
|
||||||
|
; If start of the next range is greater than ebp:ebx,
|
||||||
|
; exit the loop to 6g.
|
||||||
|
mov eax, ebx
|
||||||
|
mov edx, ebp
|
||||||
|
sub eax, dword [edi+mtrr_range.start]
|
||||||
|
sbb edx, dword [edi+mtrr_range.start+4]
|
||||||
|
jb .truncate_uc_done
|
||||||
|
; Otherwise, if end of the next range is greater than ebp:ebx,
|
||||||
|
; exit the loop to 6f.
|
||||||
|
sub eax, dword [edi+mtrr_range.length]
|
||||||
|
sbb edx, dword [edi+mtrr_range.length+4]
|
||||||
|
jb .truncate_uc_last
|
||||||
|
; Otherwise, the current range is completely within the new range.
|
||||||
|
; Free it and continue the loop if there is a next range.
|
||||||
|
; If that was a last range, exit the loop to 6g.
|
||||||
|
mov edx, [edi+mtrr_range.next]
|
||||||
|
mov eax, [.first_free_range]
|
||||||
|
mov [.first_free_range], edi
|
||||||
|
mov [edi+mtrr_range.next], eax
|
||||||
|
mov edi, edx
|
||||||
|
test edi, edi
|
||||||
|
jnz .truncate_uc_loop
|
||||||
|
jmp .truncate_uc_done
|
||||||
|
.truncate_uc_last:
|
||||||
|
; 6f. The range at edi partially intersects with the UC-range described by MTRR.
|
||||||
|
; Truncate it from the head.
|
||||||
|
mov dword [edi+mtrr_range.start], ebx
|
||||||
|
mov dword [edi+mtrr_range.start+4], ebp
|
||||||
|
neg eax
|
||||||
|
adc edx, 0
|
||||||
|
neg edx
|
||||||
|
mov dword [edi+mtrr_range.length], eax
|
||||||
|
mov dword [edi+mtrr_range.length+4], edx
|
||||||
|
.truncate_uc_done:
|
||||||
|
; 6g. We have found the next range (maybe 0) after intersection.
|
||||||
|
; Write it to [esi+mtrr_range.next].
|
||||||
|
mov [esi+mtrr_range.next], edi
|
||||||
|
.next_uc_range:
|
||||||
|
; 6h. Continue the loop 6b-6g over all configured MTRRs.
|
||||||
|
add ecx, 16
|
||||||
|
cmp ecx, [.mtrrs_end]
|
||||||
|
jb .fill_uc_ranges
|
||||||
|
; Sanity check: if there are no ranges after steps 5-6,
|
||||||
|
; fallback to step 7. Otherwise, go to 8.
|
||||||
|
cmp [.first_range], 0
|
||||||
|
jnz .ranges_ok
|
||||||
|
.fill_ranges_from_memory_map:
|
||||||
|
; 7. BIOS has not configured variable-range MTRRs.
|
||||||
|
; Create one range from 0 to [MEM_AMOUNT].
|
||||||
|
mov eax, [.first_free_range]
|
||||||
|
mov edx, [eax+mtrr_range.next]
|
||||||
|
mov [.first_free_range], edx
|
||||||
|
mov [.first_range], eax
|
||||||
|
xor edx, edx
|
||||||
|
mov [eax+mtrr_range.next], edx
|
||||||
|
mov dword [eax+mtrr_range.start], edx
|
||||||
|
mov dword [eax+mtrr_range.start+4], edx
|
||||||
|
mov ecx, [MEM_AMOUNT]
|
||||||
|
mov dword [eax+mtrr_range.length], ecx
|
||||||
|
mov dword [eax+mtrr_range.length+4], edx
|
||||||
|
.ranges_ok:
|
||||||
|
; 8. We have calculated list of WB-ranges.
|
||||||
|
; Now we should calculate a list of MTRRs so that
|
||||||
|
; * every MTRR describes a range with length = power of 2 and start that is aligned,
|
||||||
|
; * every MTRR can be WB or UC
|
||||||
|
; * (sum of all WB ranges) minus (sum of all UC ranges) equals the calculated list
|
||||||
|
; * top of 4G memory must not be covered by any ranges
|
||||||
|
; Example: range [0,0xBC000000) can be converted to
|
||||||
|
; [0,0x80000000)+[0x80000000,0xC0000000)-[0xBC000000,0xC0000000)
|
||||||
|
; WB +WB -UC
|
||||||
|
; but not to [0,0x100000000)-[0xC0000000,0x100000000)-[0xBC000000,0xC0000000).
|
||||||
|
; 8a. Check that list of ranges is [0,something) plus, optionally, [4G,something).
|
||||||
|
; This holds in practice (see mtrrtest.asm for real-life examples)
|
||||||
|
; and significantly simplifies the code: ranges are independent, start of range
|
||||||
|
; is almost always aligned (the only exception >4G upper memory can be easily covered),
|
||||||
|
; there is no need to consider adding holes before start of range, only
|
||||||
|
; append them to end of range.
|
||||||
|
xor eax, eax
|
||||||
|
mov edi, [.first_range]
|
||||||
|
cmp dword [edi+mtrr_range.start], eax
|
||||||
|
jnz .abort
|
||||||
|
cmp dword [edi+mtrr_range.start+4], eax
|
||||||
|
jnz .abort
|
||||||
|
cmp dword [edi+mtrr_range.length+4], eax
|
||||||
|
jnz .abort
|
||||||
|
mov edx, [edi+mtrr_range.next]
|
||||||
|
test edx, edx
|
||||||
|
jz @f
|
||||||
|
cmp dword [edx+mtrr_range.start], eax
|
||||||
|
jnz .abort
|
||||||
|
cmp dword [edx+mtrr_range.start+4], 1
|
||||||
|
jnz .abort
|
||||||
|
cmp [edx+mtrr_range.next], eax
|
||||||
|
jnz .abort
|
||||||
|
@@:
|
||||||
|
; 8b. Initialize: no MTRRs filled.
|
||||||
|
mov [.num_used_mtrrs], eax
|
||||||
|
lea esi, [.mtrrs]
|
||||||
|
.range2mtrr_loop:
|
||||||
|
; 8c. If we are dealing with upper-memory range (after 4G)
|
||||||
|
; with length > start, create one WB MTRR with [start,2*start),
|
||||||
|
; reset start to 2*start and return to this step.
|
||||||
|
; Example: [4G,24G) -> [4G,8G) {returning} + [8G,16G) {returning}
|
||||||
|
; + [16G,24G) {advancing to ?}.
|
||||||
|
mov eax, dword [edi+mtrr_range.length+4]
|
||||||
|
test eax, eax
|
||||||
|
jz .less4G
|
||||||
|
mov edx, dword [edi+mtrr_range.start+4]
|
||||||
|
cmp eax, edx
|
||||||
|
jb .start_aligned
|
||||||
|
inc [.num_used_mtrrs]
|
||||||
|
cmp [.num_used_mtrrs], MAX_USEFUL_MTRRS
|
||||||
|
ja .abort
|
||||||
|
mov dword [esi], MEM_WB
|
||||||
|
mov dword [esi+4], edx
|
||||||
|
mov dword [esi+8], 0
|
||||||
|
mov dword [esi+12], edx
|
||||||
|
add esi, 16
|
||||||
|
add dword [edi+mtrr_range.start+4], edx
|
||||||
|
sub dword [edi+mtrr_range.length+4], edx
|
||||||
|
jnz .range2mtrr_loop
|
||||||
|
cmp dword [edi+mtrr_range.length], 0
|
||||||
|
jz .range2mtrr_next
|
||||||
|
.less4G:
|
||||||
|
; 8d. If we are dealing with low-memory range (before 4G)
|
||||||
|
; and appending a maximal-size hole would create a range covering top of 4G,
|
||||||
|
; create a maximal-size WB range and return to this step.
|
||||||
|
; Example: for [0,0xBC000000) the following steps would consider
|
||||||
|
; variants [0,0x80000000)+(another range to be splitted) and
|
||||||
|
; [0,0x100000000)-(another range to be splitted); we forbid the last variant,
|
||||||
|
; so the first variant must be used.
|
||||||
|
bsr ecx, dword [edi+mtrr_range.length]
|
||||||
|
xor edx, edx
|
||||||
|
inc edx
|
||||||
|
shl edx, cl
|
||||||
|
lea eax, [edx*2]
|
||||||
|
add eax, dword [edi+mtrr_range.start]
|
||||||
|
jnz .start_aligned
|
||||||
|
inc [.num_used_mtrrs]
|
||||||
|
cmp [.num_used_mtrrs], MAX_USEFUL_MTRRS
|
||||||
|
ja .abort
|
||||||
|
mov eax, dword [edi+mtrr_range.start]
|
||||||
|
mov dword [esi], eax
|
||||||
|
or dword [esi], MEM_WB
|
||||||
|
mov dword [esi+4], 0
|
||||||
|
mov dword [esi+8], edx
|
||||||
|
mov dword [esi+12], 0
|
||||||
|
add esi, 16
|
||||||
|
add dword [edi+mtrr_range.start], edx
|
||||||
|
sub dword [edi+mtrr_range.length], edx
|
||||||
|
jnz .less4G
|
||||||
|
jmp .range2mtrr_next
|
||||||
|
.start_aligned:
|
||||||
|
; Start is aligned for any allowed length, maximum-size hole is allowed.
|
||||||
|
; Select the best MTRR configuration for one range.
|
||||||
|
; length=...101101
|
||||||
|
; Without hole at the end, we need one WB MTRR for every 1-bit in length:
|
||||||
|
; length=...100000 + ...001000 + ...000100 + ...000001
|
||||||
|
; We can also append one hole at the end so that one 0-bit (selected by us)
|
||||||
|
; becomes 1 and all lower bits become 0 for WB-range:
|
||||||
|
; length=...110000 - (...00010 + ...00001)
|
||||||
|
; In this way, we need one WB MTRR for every 1-bit higher than the selected bit,
|
||||||
|
; one WB MTRR for the selected bit, one UC MTRR for every 0-bit between
|
||||||
|
; the selected bit and lowest 1-bit (they become 1-bits after negation)
|
||||||
|
; and one UC MTRR for lowest 1-bit.
|
||||||
|
; So we need to select 0-bit with the maximal difference
|
||||||
|
; (number of 0-bits) - (number of 1-bits) between selected and lowest 1-bit,
|
||||||
|
; this equals the gain from using a hole. If the difference is negative for
|
||||||
|
; all 0-bits, don't append hole.
|
||||||
|
; Note that lowest 1-bit is not included when counting, but selected 0-bit is.
|
||||||
|
; 8e. Find the optimal bit position for hole.
|
||||||
|
; eax = current difference, ebx = best difference,
|
||||||
|
; ecx = hole bit position, edx = current bit position.
|
||||||
|
xor eax, eax
|
||||||
|
xor ebx, ebx
|
||||||
|
xor ecx, ecx
|
||||||
|
bsf edx, dword [edi+mtrr_range.length]
|
||||||
|
jnz @f
|
||||||
|
bsf edx, dword [edi+mtrr_range.length+4]
|
||||||
|
add edx, 32
|
||||||
|
@@:
|
||||||
|
push edx ; save position of lowest 1-bit for step 8f
|
||||||
|
.calc_stat:
|
||||||
|
inc edx
|
||||||
|
cmp edx, 64
|
||||||
|
jae .stat_done
|
||||||
|
inc eax ; increment difference in hope for 1-bit
|
||||||
|
; Note: bt conveniently works with both .length and .length+4,
|
||||||
|
; depending on whether edx>=32.
|
||||||
|
bt dword [edi+mtrr_range.length], edx
|
||||||
|
jc .calc_stat
|
||||||
|
dec eax ; hope was wrong, decrement difference to correct 'inc'
|
||||||
|
dec eax ; and again, now getting the real difference
|
||||||
|
cmp eax, ebx
|
||||||
|
jle .calc_stat
|
||||||
|
mov ebx, eax
|
||||||
|
mov ecx, edx
|
||||||
|
jmp .calc_stat
|
||||||
|
.stat_done:
|
||||||
|
; 8f. If we decided to create a hole, flip all bits between lowest and selected.
|
||||||
|
pop edx ; restore position of lowest 1-bit saved at step 8e
|
||||||
|
test ecx, ecx
|
||||||
|
jz .fill_hi_init
|
||||||
|
@@:
|
||||||
|
inc edx
|
||||||
|
cmp edx, ecx
|
||||||
|
ja .fill_hi_init
|
||||||
|
btc dword [edi+mtrr_range.length], edx
|
||||||
|
jmp @b
|
||||||
|
.fill_hi_init:
|
||||||
|
; 8g. Create MTRR ranges corresponding to upper 32 bits.
|
||||||
|
sub ecx, 32
|
||||||
|
.fill_hi_loop:
|
||||||
|
bsr edx, dword [edi+mtrr_range.length+4]
|
||||||
|
jz .fill_hi_done
|
||||||
|
inc [.num_used_mtrrs]
|
||||||
|
cmp [.num_used_mtrrs], MAX_USEFUL_MTRRS
|
||||||
|
ja .abort
|
||||||
|
mov eax, dword [edi+mtrr_range.start]
|
||||||
|
mov [esi], eax
|
||||||
|
mov eax, dword [edi+mtrr_range.start+4]
|
||||||
|
mov [esi+4], eax
|
||||||
|
xor eax, eax
|
||||||
|
mov [esi+8], eax
|
||||||
|
bts eax, edx
|
||||||
|
mov [esi+12], eax
|
||||||
|
cmp edx, ecx
|
||||||
|
jl .fill_hi_uc
|
||||||
|
or dword [esi], MEM_WB
|
||||||
|
add dword [edi+mtrr_range.start+4], eax
|
||||||
|
jmp @f
|
||||||
|
.fill_hi_uc:
|
||||||
|
sub dword [esi+4], eax
|
||||||
|
sub dword [edi+mtrr_range.start+4], eax
|
||||||
|
@@:
|
||||||
|
add esi, 16
|
||||||
|
sub dword [edi+mtrr_range.length], eax
|
||||||
|
jmp .fill_hi_loop
|
||||||
|
.fill_hi_done:
|
||||||
|
; 8h. Create MTRR ranges corresponding to lower 32 bits.
|
||||||
|
add ecx, 32
|
||||||
|
.fill_lo_loop:
|
||||||
|
bsr edx, dword [edi+mtrr_range.length]
|
||||||
|
jz .range2mtrr_next
|
||||||
|
inc [.num_used_mtrrs]
|
||||||
|
cmp [.num_used_mtrrs], MAX_USEFUL_MTRRS
|
||||||
|
ja .abort
|
||||||
|
mov eax, dword [edi+mtrr_range.start]
|
||||||
|
mov [esi], eax
|
||||||
|
mov eax, dword [edi+mtrr_range.start+4]
|
||||||
|
mov [esi+4], eax
|
||||||
|
xor eax, eax
|
||||||
|
mov [esi+12], eax
|
||||||
|
bts eax, edx
|
||||||
|
mov [esi+8], eax
|
||||||
|
cmp edx, ecx
|
||||||
|
jl .fill_lo_uc
|
||||||
|
or dword [esi], MEM_WB
|
||||||
|
add dword [edi+mtrr_range.start], eax
|
||||||
|
jmp @f
|
||||||
|
.fill_lo_uc:
|
||||||
|
sub dword [esi], eax
|
||||||
|
sub dword [edi+mtrr_range.start], eax
|
||||||
|
@@:
|
||||||
|
add esi, 16
|
||||||
|
sub dword [edi+mtrr_range.length], eax
|
||||||
|
jmp .fill_lo_loop
|
||||||
|
.range2mtrr_next:
|
||||||
|
; 8i. Repeat the loop at 8c-8h for all ranges.
|
||||||
|
mov edi, [edi+mtrr_range.next]
|
||||||
|
test edi, edi
|
||||||
|
jnz .range2mtrr_loop
|
||||||
|
; 9. We have calculated needed MTRRs, now setup them in the CPU.
|
||||||
|
; 9a. Abort if number of MTRRs is too large.
|
||||||
|
mov eax, [num_variable_mtrrs]
|
||||||
|
cmp [.num_used_mtrrs], eax
|
||||||
|
ja .abort
|
||||||
|
|
||||||
|
; 9b. Prepare for changes.
|
||||||
|
call mtrr_begin_change
|
||||||
|
|
||||||
|
; 9c. Prepare for loop over MTRRs.
|
||||||
|
lea esi, [.mtrrs]
|
||||||
|
mov ecx, 0x200
|
||||||
|
@@:
|
||||||
|
; 9d. For every MTRR, copy PHYSBASEn as is: step 8 has configured
|
||||||
|
; start value and type bits as needed.
|
||||||
|
mov eax, [esi]
|
||||||
|
mov edx, [esi+4]
|
||||||
|
wrmsr
|
||||||
|
inc ecx
|
||||||
|
; 9e. For every MTRR, calculate PHYSMASKn = -(length) or 0x800
|
||||||
|
; with upper bits cleared, 0x800 = MTRR is valid.
|
||||||
|
xor eax, eax
|
||||||
|
xor edx, edx
|
||||||
|
sub eax, [esi+8]
|
||||||
|
sbb edx, [esi+12]
|
||||||
|
or eax, 0x800
|
||||||
|
or edx, [.phys_reserved_mask]
|
||||||
|
xor edx, [.phys_reserved_mask]
|
||||||
|
wrmsr
|
||||||
|
inc ecx
|
||||||
|
; 9f. Continue steps 9d and 9e for all MTRRs calculated at step 8.
|
||||||
|
add esi, 16
|
||||||
|
dec [.num_used_mtrrs]
|
||||||
|
jnz @b
|
||||||
|
; 9g. Zero other MTRRs.
|
||||||
|
xor eax, eax
|
||||||
|
xor edx, edx
|
||||||
|
mov ebx, [num_variable_mtrrs]
|
||||||
|
lea ebx, [0x200+ebx*2]
|
||||||
|
@@:
|
||||||
|
cmp ecx, ebx
|
||||||
|
jae @f
|
||||||
|
wrmsr
|
||||||
|
inc ecx
|
||||||
|
wrmsr
|
||||||
|
inc ecx
|
||||||
|
jmp @b
|
||||||
|
@@:
|
||||||
|
|
||||||
|
; 9i. Configure MTRR_DEF_TYPE.
|
||||||
|
mov ecx, 0x2FF
|
||||||
|
rdmsr
|
||||||
|
or ah, 8 ; enable variable-ranges MTRR
|
||||||
|
and al, 0xF0; default memtype = UC
|
||||||
|
wrmsr
|
||||||
|
|
||||||
|
; 9j. Changes are done.
|
||||||
|
call mtrr_end_change
|
||||||
|
|
||||||
|
.abort:
|
||||||
|
add esp, .local_vars_size + MAX_RANGES * sizeof.mtrr_range
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
|
||||||
|
; Allocate&set one MTRR for given range.
|
||||||
|
; size must be power of 2 that divides base.
|
||||||
|
proc set_mtrr stdcall, base:dword,size:dword,mem_type:dword
|
||||||
|
; find unused register
|
||||||
|
mov ecx, 0x201
|
||||||
|
.scan:
|
||||||
|
rdmsr
|
||||||
|
dec ecx
|
||||||
|
test ah, 8
|
||||||
|
jz .found
|
||||||
|
rdmsr
|
||||||
|
test edx, edx
|
||||||
|
jnz @f
|
||||||
|
and eax, not 0xFFF ; clear reserved bits
|
||||||
|
cmp eax, [base]
|
||||||
|
jz .ret
|
||||||
|
@@:
|
||||||
|
add ecx, 3
|
||||||
|
mov eax, [num_variable_mtrrs]
|
||||||
|
lea eax, [0x200+eax*2]
|
||||||
|
cmp ecx, eax
|
||||||
|
jb .scan
|
||||||
|
; no free registers, ignore the call
|
||||||
|
.ret:
|
||||||
|
ret
|
||||||
|
.found:
|
||||||
|
; found, write values
|
||||||
|
call mtrr_begin_change
|
||||||
|
xor edx, edx
|
||||||
|
mov eax, [base]
|
||||||
|
or eax, [mem_type]
|
||||||
|
wrmsr
|
||||||
|
|
||||||
|
mov al, [cpu_phys_addr_width]
|
||||||
|
xor edx, edx
|
||||||
|
bts edx, eax
|
||||||
|
xor eax, eax
|
||||||
|
sub eax, [size]
|
||||||
|
sbb edx, 0
|
||||||
|
or eax, 0x800
|
||||||
|
inc ecx
|
||||||
|
wrmsr
|
||||||
|
call mtrr_end_change
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
|
||||||
|
; Helper procedure for mtrr_validate.
|
||||||
|
; Calculates memory type for given address according to variable-range MTRRs.
|
||||||
|
; Assumes that MTRRs are enabled.
|
||||||
|
; in: ebx = 32-bit physical address
|
||||||
|
; out: eax = memory type for ebx
|
||||||
|
proc mtrr_get_real_type
|
||||||
|
; 1. Initialize: we have not yet found any MTRRs covering ebx.
|
||||||
|
push 0
|
||||||
|
mov ecx, 0x201
|
||||||
|
.mtrr_loop:
|
||||||
|
; 2. For every MTRR, check whether it is valid; if not, continue to the next MTRR.
|
||||||
|
rdmsr
|
||||||
|
dec ecx
|
||||||
|
test ah, 8
|
||||||
|
jz .next
|
||||||
|
; 3. For every valid MTRR, check whether (ebx and PHYSMASKn) == PHYSBASEn,
|
||||||
|
; excluding low 12 bits.
|
||||||
|
and eax, ebx
|
||||||
|
push eax
|
||||||
|
rdmsr
|
||||||
|
test edx, edx
|
||||||
|
pop edx
|
||||||
|
jnz .next
|
||||||
|
xor edx, eax
|
||||||
|
and edx, not 0xFFF
|
||||||
|
jnz .next
|
||||||
|
; 4. If so, set the bit corresponding to memory type defined by this MTRR.
|
||||||
|
and eax, 7
|
||||||
|
bts [esp], eax
|
||||||
|
.next:
|
||||||
|
; 5. Continue loop at 2-4 for all variable-range MTRRs.
|
||||||
|
add ecx, 3
|
||||||
|
mov eax, [num_variable_mtrrs]
|
||||||
|
lea eax, [0x200+eax*2]
|
||||||
|
cmp ecx, eax
|
||||||
|
jb .mtrr_loop
|
||||||
|
; 6. If no MTRRs cover address in ebx, use default MTRR type from MTRR_DEF_CAP.
|
||||||
|
pop edx
|
||||||
|
test edx, edx
|
||||||
|
jz .default
|
||||||
|
; 7. Find&clear 1-bit in edx.
|
||||||
|
bsf eax, edx
|
||||||
|
btr edx, eax
|
||||||
|
; 8. If there was only one 1-bit, then all MTRRs are consistent, return that bit.
|
||||||
|
test edx, edx
|
||||||
|
jz .nothing
|
||||||
|
; Otherwise, return MEM_UC (e.g. WB+UC is UC).
|
||||||
|
xor eax, eax
|
||||||
|
.nothing:
|
||||||
|
ret
|
||||||
|
.default:
|
||||||
|
mov ecx, 0x2FF
|
||||||
|
rdmsr
|
||||||
|
movzx eax, al
|
||||||
|
ret
|
||||||
|
endp
|
||||||
|
|
||||||
|
; If MTRRs are configured improperly, this is not obvious to the user;
|
||||||
|
; everything works, but the performance can be horrible.
|
||||||
|
; Try to detect this and let the user know that the low performance
|
||||||
|
; is caused by some problem and is not a global property of the system.
|
||||||
|
; Let's hope he would report it to developers...
|
||||||
|
proc mtrr_validate
|
||||||
|
; 1. If MTRRs are not supported, they cannot be configured improperly.
|
||||||
|
; Note: VirtualBox claims MTRR support in cpuid, but emulates MTRRCAP=0,
|
||||||
|
; which is efficiently equivalent to absent MTRRs.
|
||||||
|
; So check [num_variable_mtrrs] instead of CAPS_MTRR in [cpu_caps].
|
||||||
|
cmp [num_variable_mtrrs], 0
|
||||||
|
jz .exit
|
||||||
|
; 2. If variable-range MTRRs are not configured, this is a problem.
|
||||||
|
mov ecx, 0x2FF
|
||||||
|
rdmsr
|
||||||
|
test ah, 8
|
||||||
|
jz .fail
|
||||||
|
; 3. Get the memory type for address somewhere inside working memory.
|
||||||
|
; It must be write-back.
|
||||||
|
mov ebx, 0x27FFFF
|
||||||
|
call mtrr_get_real_type
|
||||||
|
cmp al, MEM_WB
|
||||||
|
jnz .fail
|
||||||
|
; 4. If we're using a mode with LFB,
|
||||||
|
; get the memory type for last pixel of the framebuffer.
|
||||||
|
; It must be write-combined.
|
||||||
|
test word [SCR_MODE], 0x4000
|
||||||
|
jz .exit
|
||||||
|
mov eax, [_display.pitch]
|
||||||
|
mul [_display.height]
|
||||||
|
dec eax
|
||||||
|
; LFB is mapped to virtual address LFB_BASE,
|
||||||
|
; it uses global pages if supported by CPU.
|
||||||
|
mov ebx, [sys_proc+PROC.pdt_0+(LFB_BASE shr 20)]
|
||||||
|
test ebx, PG_LARGE
|
||||||
|
jnz @f
|
||||||
|
mov ebx, [page_tabs+(LFB_BASE shr 10)]
|
||||||
|
@@:
|
||||||
|
and ebx, not 0xFFF
|
||||||
|
add ebx, eax
|
||||||
|
call mtrr_get_real_type
|
||||||
|
cmp al, MEM_WC
|
||||||
|
jz .exit
|
||||||
|
; 5. The check at step 4 fails on Bochs:
|
||||||
|
; Bochs BIOS configures MTRRs in a strange way not respecting [cpu_phys_addr_width],
|
||||||
|
; so mtrr_reconfigure avoids to touch anything.
|
||||||
|
; However, Bochs core ignores MTRRs (keeping them only for rdmsr/wrmsr),
|
||||||
|
; so we don't care about proper setting for Bochs.
|
||||||
|
; Use northbridge PCI id to detect Bochs: it emulates either i440fx or i430fx
|
||||||
|
; depending on configuration file.
|
||||||
|
mov eax, [pcidev_list.fd]
|
||||||
|
cmp eax, pcidev_list ; sanity check: fail if no PCI devices
|
||||||
|
jz .fail
|
||||||
|
cmp [eax+PCIDEV.vendor_device_id], 0x12378086
|
||||||
|
jz .exit
|
||||||
|
cmp [eax+PCIDEV.vendor_device_id], 0x01228086
|
||||||
|
jnz .fail
|
||||||
|
.exit:
|
||||||
|
ret
|
||||||
|
.fail:
|
||||||
|
mov ebx, mtrr_user_message
|
||||||
|
mov ebp, notifyapp
|
||||||
|
call fs_execute_from_sysdir_param
|
||||||
|
ret
|
||||||
|
endp
|
@ -14,9 +14,7 @@ DEBUG_SHOW_IO = 0
|
|||||||
|
|
||||||
struct V86_machine
|
struct V86_machine
|
||||||
; page directory
|
; page directory
|
||||||
pagedir dd ?
|
process dd ?
|
||||||
; translation table: V86 address -> flat linear address
|
|
||||||
pages dd ?
|
|
||||||
; mutex to protect all data from writing by multiple threads at one time
|
; mutex to protect all data from writing by multiple threads at one time
|
||||||
mutex dd ?
|
mutex dd ?
|
||||||
; i/o permission map
|
; i/o permission map
|
||||||
@ -38,91 +36,87 @@ v86_create:
|
|||||||
and dword [eax+V86_machine.mutex], 0
|
and dword [eax+V86_machine.mutex], 0
|
||||||
; allocate tables
|
; allocate tables
|
||||||
mov ebx, eax
|
mov ebx, eax
|
||||||
; We allocate 4 pages.
|
|
||||||
; First is main page directory for V86 mode.
|
stdcall create_process, 4096, OS_BASE, 4096
|
||||||
; Second page:
|
test eax, eax
|
||||||
; first half (0x800 bytes) is page table for addresses 0 - 0x100000,
|
jz .fail2
|
||||||
; second half is for V86-to-linear translation.
|
|
||||||
; Third and fourth are for I/O permission map.
|
mov [eax+PROC.mem_used], 4096
|
||||||
push 8000h ; blocks less than 8 pages are discontinuous
|
mov [ebx+V86_machine.process], eax
|
||||||
|
|
||||||
|
push 2000h
|
||||||
call kernel_alloc
|
call kernel_alloc
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .fail2
|
jz .fail2
|
||||||
mov [ebx+V86_machine.pagedir], eax
|
|
||||||
push edi eax
|
mov [ebx+V86_machine.iopm], eax
|
||||||
mov edi, eax
|
|
||||||
add eax, 1800h
|
|
||||||
mov [ebx+V86_machine.pages], eax
|
|
||||||
; initialize tables
|
; initialize tables
|
||||||
mov ecx, 2000h/4
|
push edi
|
||||||
xor eax, eax
|
|
||||||
rep stosd
|
|
||||||
mov [ebx+V86_machine.iopm], edi
|
|
||||||
dec eax
|
|
||||||
mov ecx, 2000h/4
|
|
||||||
rep stosd
|
|
||||||
pop eax
|
|
||||||
; page directory: first entry is page table...
|
|
||||||
mov edi, eax
|
mov edi, eax
|
||||||
add eax, 1000h
|
mov eax, -1
|
||||||
push eax
|
mov ecx, 2000h/4
|
||||||
call get_pg_addr
|
rep stosd
|
||||||
or al, PG_UW
|
|
||||||
stosd
|
mov eax, [ebx+V86_machine.process]
|
||||||
; ...and also copy system page tables
|
mov eax, [eax+PROC.pdt_0_phys]
|
||||||
; thx to Serge, system is located at high addresses
|
|
||||||
add edi, (OS_BASE shr 20) - 4
|
pushfd
|
||||||
push esi
|
cli
|
||||||
mov esi, sys_proc+PROC.pdt_0+(OS_BASE shr 20)
|
mov cr3, eax
|
||||||
mov ecx, 0x80000000 shr 22
|
|
||||||
rep movsd
|
|
||||||
|
|
||||||
mov eax, [ebx+V86_machine.pagedir] ;root dir also is
|
|
||||||
call get_pg_addr ;used as page table
|
|
||||||
or al, PG_SW
|
|
||||||
mov [edi-4096+(page_tabs shr 20)], eax
|
|
||||||
|
|
||||||
pop esi
|
|
||||||
; now V86 specific: initialize known addresses in first Mb
|
; now V86 specific: initialize known addresses in first Mb
|
||||||
pop eax
|
|
||||||
; first page - BIOS data (shared between all machines!)
|
; first page - BIOS data (shared between all machines!)
|
||||||
; physical address = 0
|
; physical address = 0
|
||||||
; linear address = OS_BASE
|
; linear address = OS_BASE
|
||||||
mov dword [eax], 111b
|
|
||||||
mov dword [eax+800h], OS_BASE
|
|
||||||
; page before 0xA0000 - Extended BIOS Data Area (shared between all machines!)
|
; page before 0xA0000 - Extended BIOS Data Area (shared between all machines!)
|
||||||
; physical address = 0x9C000
|
; physical address = 0x9C000
|
||||||
; linear address = 0x8009C000
|
; linear address = 0x8009C000
|
||||||
; (I have seen one computer with EBDA segment = 0x9D80,
|
; (I have seen one computer with EBDA segment = 0x9D80,
|
||||||
; all other computers use less memory)
|
; all other computers use less memory)
|
||||||
mov ecx, 4
|
|
||||||
mov edx, 0x9C000
|
mov eax, PG_UW
|
||||||
push eax
|
mov [page_tabs], eax
|
||||||
lea edi, [eax+0x9C*4]
|
invlpg [eax]
|
||||||
|
|
||||||
|
mov byte [0x500], 0xCD
|
||||||
|
mov byte [0x501], 0x13
|
||||||
|
mov byte [0x502], 0xF4
|
||||||
|
mov byte [0x503], 0xCD
|
||||||
|
mov byte [0x504], 0x10
|
||||||
|
mov byte [0x505], 0xF4
|
||||||
|
|
||||||
|
mov eax, 0x99000+PG_UW
|
||||||
|
mov edi, page_tabs+0x99*4
|
||||||
|
mov edx, 0x1000
|
||||||
|
mov ecx, 7
|
||||||
@@:
|
@@:
|
||||||
lea eax, [edx + OS_BASE]
|
|
||||||
mov [edi+800h], eax
|
|
||||||
lea eax, [edx + 111b]
|
|
||||||
stosd
|
stosd
|
||||||
add edx, 0x1000
|
add eax, edx
|
||||||
loop @b
|
loop @b
|
||||||
pop eax
|
|
||||||
pop edi
|
|
||||||
; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!)
|
; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!)
|
||||||
; physical address = 0xC0000
|
; physical address = 0xC0000
|
||||||
; linear address = 0x800C0000
|
|
||||||
mov ecx, 0xC0
|
mov eax, 0xC0000+PG_UW
|
||||||
|
mov edi, page_tabs+0xC0*4
|
||||||
|
mov edx, 0x1000
|
||||||
|
mov ecx, 64
|
||||||
@@:
|
@@:
|
||||||
mov edx, ecx
|
stosd
|
||||||
shl edx, 12
|
add eax, edx
|
||||||
push edx
|
loop @b
|
||||||
or edx, 111b
|
|
||||||
mov [eax+ecx*4], edx
|
mov eax, sys_proc-OS_BASE+PROC.pdt_0
|
||||||
pop edx
|
|
||||||
add edx, OS_BASE
|
mov cr3, eax
|
||||||
mov [eax+ecx*4+0x800], edx
|
popfd
|
||||||
inc cl
|
|
||||||
jnz @b
|
pop edi
|
||||||
|
|
||||||
mov eax, ebx
|
mov eax, ebx
|
||||||
ret
|
ret
|
||||||
.fail2:
|
.fail2:
|
||||||
@ -132,15 +126,16 @@ v86_create:
|
|||||||
xor eax, eax
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
;not used
|
||||||
; Destroy V86 machine
|
; Destroy V86 machine
|
||||||
; in: eax = handle
|
; in: eax = handle
|
||||||
; out: nothing
|
; out: nothing
|
||||||
; destroys: eax, ebx, ecx, edx (due to free)
|
; destroys: eax, ebx, ecx, edx (due to free)
|
||||||
v86_destroy:
|
;v86_destroy:
|
||||||
push eax
|
; push eax
|
||||||
stdcall kernel_free, [eax+V86_machine.pagedir]
|
; stdcall kernel_free, [eax+V86_machine.pagedir]
|
||||||
pop eax
|
; pop eax
|
||||||
jmp free
|
; jmp free
|
||||||
|
|
||||||
; Translate V86-address to linear address
|
; Translate V86-address to linear address
|
||||||
; in: eax=V86 address
|
; in: eax=V86 address
|
||||||
@ -150,28 +145,29 @@ v86_destroy:
|
|||||||
v86_get_lin_addr:
|
v86_get_lin_addr:
|
||||||
push ecx edx
|
push ecx edx
|
||||||
mov ecx, eax
|
mov ecx, eax
|
||||||
mov edx, [esi+V86_machine.pages]
|
mov edx, page_tabs
|
||||||
shr ecx, 12
|
shr ecx, 12
|
||||||
and eax, 0xFFF
|
and eax, 0xFFF
|
||||||
add eax, [edx+ecx*4] ; atomic operation, no mutex needed
|
add eax, [edx+ecx*4] ; atomic operation, no mutex needed
|
||||||
pop edx ecx
|
pop edx ecx
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
;not used
|
||||||
; Sets linear address for V86-page
|
; Sets linear address for V86-page
|
||||||
; in: eax=linear address (must be page-aligned)
|
; in: eax=linear address (must be page-aligned)
|
||||||
; ecx=V86 page (NOT address!)
|
; ecx=V86 page (NOT address!)
|
||||||
; esi=handle
|
; esi=handle
|
||||||
; out: nothing
|
; out: nothing
|
||||||
; destroys: nothing
|
; destroys: nothing
|
||||||
v86_set_page:
|
;v86_set_page:
|
||||||
push eax ebx
|
; push eax ebx
|
||||||
mov ebx, [esi+V86_machine.pagedir]
|
; mov ebx, [esi+V86_machine.pagedir]
|
||||||
mov [ebx+ecx*4+0x1800], eax
|
; mov [ebx+ecx*4+0x1800], eax
|
||||||
call get_pg_addr
|
; call get_pg_addr
|
||||||
or al, 111b
|
; or al, 111b
|
||||||
mov [ebx+ecx*4+0x1000], eax
|
; mov [ebx+ecx*4+0x1000], eax
|
||||||
pop ebx eax
|
; pop ebx eax
|
||||||
ret
|
; ret
|
||||||
|
|
||||||
; Allocate memory in V86 machine
|
; Allocate memory in V86 machine
|
||||||
; in: eax=size (in bytes)
|
; in: eax=size (in bytes)
|
||||||
@ -214,21 +210,7 @@ init_sys_v86:
|
|||||||
mov [sys_v86_machine], eax
|
mov [sys_v86_machine], eax
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .ret
|
jz .ret
|
||||||
mov byte [OS_BASE + 0x500], 0xCD
|
|
||||||
mov byte [OS_BASE + 0x501], 0x13
|
|
||||||
mov byte [OS_BASE + 0x502], 0xF4
|
|
||||||
mov byte [OS_BASE + 0x503], 0xCD
|
|
||||||
mov byte [OS_BASE + 0x504], 0x10
|
|
||||||
mov byte [OS_BASE + 0x505], 0xF4
|
|
||||||
mov esi, eax
|
mov esi, eax
|
||||||
mov ebx, [eax+V86_machine.pagedir]
|
|
||||||
; one page for stack, two pages for results (0x2000 bytes = 16 sectors)
|
|
||||||
mov dword [ebx+0x99*4+0x1000], 0x99000 or 111b
|
|
||||||
mov dword [ebx+0x99*4+0x1800], OS_BASE + 0x99000
|
|
||||||
mov dword [ebx+0x9A*4+0x1000], 0x9A000 or 111b
|
|
||||||
mov dword [ebx+0x9A*4+0x1800], OS_BASE + 0x9A000
|
|
||||||
mov dword [ebx+0x9B*4+0x1000], 0x9B000 or 111b
|
|
||||||
mov dword [ebx+0x9B*4+0x1800], OS_BASE + 0x9B000
|
|
||||||
if ~DEBUG_SHOW_IO
|
if ~DEBUG_SHOW_IO
|
||||||
; allow access to all ports
|
; allow access to all ports
|
||||||
mov ecx, [esi+V86_machine.iopm]
|
mov ecx, [esi+V86_machine.iopm]
|
||||||
@ -272,6 +254,9 @@ ends
|
|||||||
; eax = 3 - IRQ is already hooked by another VM
|
; eax = 3 - IRQ is already hooked by another VM
|
||||||
; destroys: nothing
|
; destroys: nothing
|
||||||
v86_start:
|
v86_start:
|
||||||
|
|
||||||
|
xchg bx, bx
|
||||||
|
|
||||||
pushad
|
pushad
|
||||||
|
|
||||||
cli
|
cli
|
||||||
@ -296,12 +281,10 @@ v86_start:
|
|||||||
mov [ecx+APPDATA.saved_esp0], esp
|
mov [ecx+APPDATA.saved_esp0], esp
|
||||||
mov [tss._esp0], esp
|
mov [tss._esp0], esp
|
||||||
|
|
||||||
mov eax, [esi+V86_machine.pagedir]
|
mov eax, [esi+V86_machine.process]
|
||||||
call get_pg_addr
|
|
||||||
mov [ecx+APPDATA.process], eax
|
mov [ecx+APPDATA.process], eax
|
||||||
; mov cr3, eax
|
mov eax, [eax+PROC.pdt_0_phys]
|
||||||
|
mov cr3, eax
|
||||||
; mov [irq_tab+5*4], my05
|
|
||||||
|
|
||||||
; We do not enable interrupts, because V86 IRQ redirector assumes that
|
; We do not enable interrupts, because V86 IRQ redirector assumes that
|
||||||
; machine is running
|
; machine is running
|
||||||
@ -795,6 +778,7 @@ end if
|
|||||||
pop ebx
|
pop ebx
|
||||||
mov dword [SLOT_BASE+ecx+APPDATA.io_map], ebx
|
mov dword [SLOT_BASE+ecx+APPDATA.io_map], ebx
|
||||||
mov dword [page_tabs + (tss._io_map_0 shr 10)], ebx
|
mov dword [page_tabs + (tss._io_map_0 shr 10)], ebx
|
||||||
|
mov eax, [eax+PROC.pdt_0_phys]
|
||||||
mov cr3, eax
|
mov cr3, eax
|
||||||
sti
|
sti
|
||||||
|
|
||||||
@ -843,8 +827,7 @@ v86_irq:
|
|||||||
pop eax
|
pop eax
|
||||||
v86_irq2:
|
v86_irq2:
|
||||||
mov esi, [v86_irqhooks+edi*8] ; get VM handle
|
mov esi, [v86_irqhooks+edi*8] ; get VM handle
|
||||||
mov eax, [esi+V86_machine.pagedir]
|
mov eax, [esi+V86_machine.process]
|
||||||
call get_pg_addr
|
|
||||||
mov ecx, [CURRENT_TASK]
|
mov ecx, [CURRENT_TASK]
|
||||||
shl ecx, 8
|
shl ecx, 8
|
||||||
cmp [SLOT_BASE+ecx+APPDATA.process], eax
|
cmp [SLOT_BASE+ecx+APPDATA.process], eax
|
||||||
@ -895,6 +878,7 @@ v86_irq2:
|
|||||||
popad
|
popad
|
||||||
iretd
|
iretd
|
||||||
.found:
|
.found:
|
||||||
|
mov eax, [eax+PROC.pdt_0_phys]
|
||||||
mov cr3, eax
|
mov cr3, eax
|
||||||
mov esi, [ebx+APPDATA.saved_esp0]
|
mov esi, [ebx+APPDATA.saved_esp0]
|
||||||
sub word [esi-sizeof.v86_regs+v86_regs.esp], 6
|
sub word [esi-sizeof.v86_regs+v86_regs.esp], 6
|
||||||
|
459
kernel/branches/kolibri-process/detect/init_ata.inc
Normal file
459
kernel/branches/kolibri-process/detect/init_ata.inc
Normal file
@ -0,0 +1,459 @@
|
|||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; ;;
|
||||||
|
;; Copyright (C) KolibriOS team 2014. All rights reserved. ;;
|
||||||
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
|
;; ;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
$Revision: 4850 $
|
||||||
|
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
; find the IDE controller in the device list
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
mov ecx, IDE_controller_1
|
||||||
|
mov esi, pcidev_list
|
||||||
|
;--------------------------------------
|
||||||
|
align 4
|
||||||
|
.loop:
|
||||||
|
mov esi, [esi+PCIDEV.fd]
|
||||||
|
cmp esi, pcidev_list
|
||||||
|
jz find_IDE_controller_done
|
||||||
|
|
||||||
|
mov eax, [esi+PCIDEV.class]
|
||||||
|
shr eax, 4
|
||||||
|
cmp eax, 0x01018
|
||||||
|
jnz .loop
|
||||||
|
;--------------------------------------
|
||||||
|
.found:
|
||||||
|
mov eax, [esi+PCIDEV.class]
|
||||||
|
DEBUGF 1, 'K : IDE controller programming interface %x\n', eax
|
||||||
|
mov [ecx+IDE_DATA.ProgrammingInterface], eax
|
||||||
|
|
||||||
|
mov ah, [esi+PCIDEV.bus]
|
||||||
|
mov al, 2
|
||||||
|
mov bh, [esi+PCIDEV.devfn]
|
||||||
|
;--------------------------------------
|
||||||
|
mov dx, 0x1F0
|
||||||
|
test byte [esi+PCIDEV.class], 1
|
||||||
|
jz @f
|
||||||
|
mov bl, 0x10
|
||||||
|
push eax
|
||||||
|
call pci_read_reg
|
||||||
|
and eax, 0xFFFC
|
||||||
|
mov edx, eax
|
||||||
|
pop eax
|
||||||
|
@@:
|
||||||
|
DEBUGF 1, 'K : BAR0 IDE base addr %x\n', dx
|
||||||
|
mov [StandardATABases], dx
|
||||||
|
mov [ecx+IDE_DATA.BAR0_val], dx
|
||||||
|
;--------------------------------------
|
||||||
|
mov dx, 0x3F4
|
||||||
|
test byte [esi+PCIDEV.class], 1
|
||||||
|
jz @f
|
||||||
|
mov bl, 0x14
|
||||||
|
push eax
|
||||||
|
call pci_read_reg
|
||||||
|
and eax, 0xFFFC
|
||||||
|
mov edx, eax
|
||||||
|
pop eax
|
||||||
|
@@:
|
||||||
|
DEBUGF 1, 'K : BAR1 IDE base addr %x\n', dx
|
||||||
|
mov [ecx+IDE_DATA.BAR1_val], dx
|
||||||
|
;--------------------------------------
|
||||||
|
mov dx, 0x170
|
||||||
|
test byte [esi+PCIDEV.class], 4
|
||||||
|
jz @f
|
||||||
|
mov bl, 0x18
|
||||||
|
push eax
|
||||||
|
call pci_read_reg
|
||||||
|
and eax, 0xFFFC
|
||||||
|
mov edx, eax
|
||||||
|
pop eax
|
||||||
|
@@:
|
||||||
|
DEBUGF 1, 'K : BAR2 IDE base addr %x\n', dx
|
||||||
|
mov [StandardATABases+2], dx
|
||||||
|
mov [ecx+IDE_DATA.BAR2_val], dx
|
||||||
|
;--------------------------------------
|
||||||
|
mov dx, 0x374
|
||||||
|
test byte [esi+PCIDEV.class], 4
|
||||||
|
jz @f
|
||||||
|
mov bl, 0x1C
|
||||||
|
push eax
|
||||||
|
call pci_read_reg
|
||||||
|
and eax, 0xFFFC
|
||||||
|
mov edx, eax
|
||||||
|
pop eax
|
||||||
|
@@:
|
||||||
|
DEBUGF 1, 'K : BAR3 IDE base addr %x\n', dx
|
||||||
|
mov [ecx+IDE_DATA.BAR3_val], dx
|
||||||
|
;--------------------------------------
|
||||||
|
mov bl, 0x20
|
||||||
|
push eax
|
||||||
|
call pci_read_reg
|
||||||
|
and eax, 0xFFFC
|
||||||
|
DEBUGF 1, 'K : BAR4 IDE controller register base addr %x\n', ax
|
||||||
|
mov [ecx+IDE_DATA.RegsBaseAddres], ax
|
||||||
|
pop eax
|
||||||
|
;--------------------------------------
|
||||||
|
mov bl, 0x3C
|
||||||
|
push eax
|
||||||
|
call pci_read_reg
|
||||||
|
and eax, 0xFF
|
||||||
|
DEBUGF 1, 'K : IDE Interrupt %x\n', al
|
||||||
|
mov [ecx+IDE_DATA.Interrupt], ax
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
add ecx, sizeof.IDE_DATA
|
||||||
|
;--------------------------------------
|
||||||
|
jmp .loop
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
uglobal
|
||||||
|
align 4
|
||||||
|
;--------------------------------------
|
||||||
|
IDE_controller_pointer dd ?
|
||||||
|
;--------------------------------------
|
||||||
|
IDE_controller_1 IDE_DATA
|
||||||
|
IDE_controller_2 IDE_DATA
|
||||||
|
IDE_controller_3 IDE_DATA
|
||||||
|
;--------------------------------------
|
||||||
|
cache_ide0 IDE_CACHE
|
||||||
|
cache_ide1 IDE_CACHE
|
||||||
|
cache_ide2 IDE_CACHE
|
||||||
|
cache_ide3 IDE_CACHE
|
||||||
|
cache_ide4 IDE_CACHE
|
||||||
|
cache_ide5 IDE_CACHE
|
||||||
|
cache_ide6 IDE_CACHE
|
||||||
|
cache_ide7 IDE_CACHE
|
||||||
|
cache_ide8 IDE_CACHE
|
||||||
|
cache_ide9 IDE_CACHE
|
||||||
|
cache_ide10 IDE_CACHE
|
||||||
|
cache_ide11 IDE_CACHE
|
||||||
|
;--------------------------------------
|
||||||
|
IDE_device_1 rd 2
|
||||||
|
IDE_device_2 rd 2
|
||||||
|
IDE_device_3 rd 2
|
||||||
|
;--------------------------------------
|
||||||
|
endg
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
; START of initialisation IDE ATA code
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
Init_IDE_ATA_controller:
|
||||||
|
cmp [ecx+IDE_DATA.ProgrammingInterface], 0
|
||||||
|
jne @f
|
||||||
|
|
||||||
|
ret
|
||||||
|
;--------------------------------------
|
||||||
|
@@:
|
||||||
|
mov esi, boot_disabling_ide
|
||||||
|
call boot_log
|
||||||
|
;--------------------------------------
|
||||||
|
; Disable IDE interrupts, because the search
|
||||||
|
; for IDE partitions is in the PIO mode.
|
||||||
|
;--------------------------------------
|
||||||
|
.disable_IDE_interrupt:
|
||||||
|
; Disable interrupts in IDE controller for PIO
|
||||||
|
mov al, 2
|
||||||
|
mov dx, [ecx+IDE_DATA.BAR1_val] ;0x3F4
|
||||||
|
add dx, 2 ;0x3F6
|
||||||
|
out dx, al
|
||||||
|
mov dx, [ecx+IDE_DATA.BAR3_val] ;0x374
|
||||||
|
add dx, 2 ;0x376
|
||||||
|
out dx, al
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
; set current ata bases
|
||||||
|
@@:
|
||||||
|
mov ax, [ecx+IDE_DATA.BAR0_val]
|
||||||
|
mov [StandardATABases], ax
|
||||||
|
mov ax, [ecx+IDE_DATA.BAR2_val]
|
||||||
|
mov [StandardATABases+2], ax
|
||||||
|
|
||||||
|
mov esi, boot_detecthdcd
|
||||||
|
call boot_log
|
||||||
|
;--------------------------------------
|
||||||
|
include 'dev_hdcd.inc'
|
||||||
|
;--------------------------------------
|
||||||
|
ret
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
Init_IDE_ATA_controller_2:
|
||||||
|
cmp [ecx+IDE_DATA.ProgrammingInterface], 0
|
||||||
|
jne @f
|
||||||
|
|
||||||
|
ret
|
||||||
|
;--------------------------------------
|
||||||
|
@@:
|
||||||
|
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
|
||||||
|
; test whether it is our interrupt?
|
||||||
|
add dx, 2
|
||||||
|
in al, dx
|
||||||
|
test al, 100b
|
||||||
|
jz @f
|
||||||
|
; clear Bus Master IDE Status register
|
||||||
|
; clear Interrupt bit
|
||||||
|
out dx, al
|
||||||
|
;--------------------------------------
|
||||||
|
@@:
|
||||||
|
add dx, 8
|
||||||
|
; test whether it is our interrupt?
|
||||||
|
in al, dx
|
||||||
|
test al, 100b
|
||||||
|
jz @f
|
||||||
|
; clear Bus Master IDE Status register
|
||||||
|
; clear Interrupt bit
|
||||||
|
out dx, al
|
||||||
|
;--------------------------------------
|
||||||
|
@@:
|
||||||
|
; read status register and remove the interrupt request
|
||||||
|
mov dx, [ecx+IDE_DATA.BAR0_val] ;0x1F0
|
||||||
|
add dx, 0x7 ;0x1F7
|
||||||
|
in al, dx
|
||||||
|
mov dx, [ecx+IDE_DATA.BAR2_val] ;0x170
|
||||||
|
add dx, 0x7 ;0x177
|
||||||
|
in al, dx
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
; push eax edx
|
||||||
|
; mov dx, [ecx+IDE_DATA.RegsBaseAddres]
|
||||||
|
; xor eax, eax
|
||||||
|
; add dx, 2
|
||||||
|
; in al, dx
|
||||||
|
; DEBUGF 1, "K : Primary Bus Master IDE Status Register %x\n", eax
|
||||||
|
|
||||||
|
; add dx, 8
|
||||||
|
; in al, dx
|
||||||
|
; DEBUGF 1, "K : Secondary Bus Master IDE Status Register %x\n", eax
|
||||||
|
; pop edx eax
|
||||||
|
|
||||||
|
; cmp [ecx+IDE_DATA.RegsBaseAddres], 0
|
||||||
|
; setnz [ecx+IDE_DATA.dma_hdd]
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
; set interrupts for IDE Controller
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
pushfd
|
||||||
|
cli
|
||||||
|
.enable_IDE_interrupt:
|
||||||
|
mov esi, boot_enabling_ide
|
||||||
|
call boot_log
|
||||||
|
; Enable interrupts in IDE controller for DMA
|
||||||
|
xor ebx, ebx
|
||||||
|
cmp ecx, IDE_controller_2
|
||||||
|
jne @f
|
||||||
|
|
||||||
|
add ebx, 5
|
||||||
|
jmp .check_DRIVE_DATA
|
||||||
|
;--------------------------------------
|
||||||
|
@@:
|
||||||
|
cmp ecx, IDE_controller_3
|
||||||
|
jne .check_DRIVE_DATA
|
||||||
|
|
||||||
|
add ebx, 10
|
||||||
|
;--------------------------------------
|
||||||
|
.check_DRIVE_DATA:
|
||||||
|
mov al, 0
|
||||||
|
mov ah, [ebx+DRIVE_DATA+1]
|
||||||
|
test ah, 10100000b ; check for ATAPI devices
|
||||||
|
jz @f
|
||||||
|
;--------------------------------------
|
||||||
|
.ch1_pio_set_ATAPI:
|
||||||
|
DEBUGF 1, "K : IDE CH1 PIO, because ATAPI drive present\n"
|
||||||
|
jmp .ch1_pio_set_for_all
|
||||||
|
;--------------------------------------
|
||||||
|
.ch1_pio_set_no_devices:
|
||||||
|
DEBUGF 1, "K : IDE CH1 PIO because no devices\n"
|
||||||
|
jmp .ch1_pio_set_for_all
|
||||||
|
;-------------------------------------
|
||||||
|
.ch1_pio_set:
|
||||||
|
DEBUGF 1, "K : IDE CH1 PIO because device not support UDMA\n"
|
||||||
|
;-------------------------------------
|
||||||
|
.ch1_pio_set_for_all:
|
||||||
|
mov [ecx+IDE_DATA.dma_hdd_channel_1], al
|
||||||
|
jmp .ch2_check
|
||||||
|
;--------------------------------------
|
||||||
|
@@:
|
||||||
|
xor ebx, ebx
|
||||||
|
call calculate_IDE_device_values_storage
|
||||||
|
|
||||||
|
test ah, 1010000b
|
||||||
|
jz .ch1_pio_set_no_devices
|
||||||
|
|
||||||
|
test ah, 1000000b
|
||||||
|
jz @f
|
||||||
|
|
||||||
|
cmp [ebx+IDE_DEVICE.UDMA_possible_modes], al
|
||||||
|
je .ch1_pio_set
|
||||||
|
|
||||||
|
cmp [ebx+IDE_DEVICE.UDMA_set_mode], al
|
||||||
|
je .ch1_pio_set
|
||||||
|
;--------------------------------------
|
||||||
|
@@:
|
||||||
|
test ah, 10000b
|
||||||
|
jz @f
|
||||||
|
|
||||||
|
add ebx, 2
|
||||||
|
|
||||||
|
cmp [ebx+IDE_DEVICE.UDMA_possible_modes], al
|
||||||
|
je .ch1_pio_set
|
||||||
|
|
||||||
|
cmp [ebx+IDE_DEVICE.UDMA_set_mode], al
|
||||||
|
je .ch1_pio_set
|
||||||
|
;--------------------------------------
|
||||||
|
@@:
|
||||||
|
mov dx, [ecx+IDE_DATA.BAR1_val] ;0x3F4
|
||||||
|
add dx, 2 ;0x3F6
|
||||||
|
out dx, al
|
||||||
|
DEBUGF 1, "K : IDE CH1 DMA enabled\n"
|
||||||
|
mov [ecx+IDE_DATA.dma_hdd_channel_1], byte 1
|
||||||
|
;--------------------------------------
|
||||||
|
.ch2_check:
|
||||||
|
test ah, 1010b ; check for ATAPI devices
|
||||||
|
jz @f
|
||||||
|
;--------------------------------------
|
||||||
|
.ch2_pio_set_ATAPI:
|
||||||
|
DEBUGF 1, "K : IDE CH2 PIO, because ATAPI drive present\n"
|
||||||
|
jmp .ch2_pio_set_for_all
|
||||||
|
;--------------------------------------
|
||||||
|
.ch2_pio_set_no_devices:
|
||||||
|
DEBUGF 1, "K : IDE CH2 PIO because no devices\n"
|
||||||
|
jmp .ch2_pio_set_for_all
|
||||||
|
;--------------------------------------
|
||||||
|
.ch2_pio_set:
|
||||||
|
DEBUGF 1, "K : IDE CH2 PIO because device not support UDMA\n"
|
||||||
|
;--------------------------------------
|
||||||
|
.ch2_pio_set_for_all:
|
||||||
|
mov [ecx+IDE_DATA.dma_hdd_channel_2], al
|
||||||
|
jmp .set_interrupts_for_IDE_controllers
|
||||||
|
;--------------------------------------
|
||||||
|
@@:
|
||||||
|
mov ebx, 4
|
||||||
|
call calculate_IDE_device_values_storage
|
||||||
|
|
||||||
|
test ah, 101b
|
||||||
|
jz .ch2_pio_set_no_devices
|
||||||
|
|
||||||
|
test ah, 100b
|
||||||
|
jz @f
|
||||||
|
|
||||||
|
cmp [ebx+IDE_DEVICE.UDMA_possible_modes], al
|
||||||
|
je .ch2_pio_set
|
||||||
|
|
||||||
|
cmp [ebx+IDE_DEVICE.UDMA_set_mode], al
|
||||||
|
je .ch2_pio_set
|
||||||
|
;--------------------------------------
|
||||||
|
@@:
|
||||||
|
test ah, 1b
|
||||||
|
jz @f
|
||||||
|
|
||||||
|
add ebx, 2
|
||||||
|
|
||||||
|
cmp [ebx+IDE_DEVICE.UDMA_possible_modes], al
|
||||||
|
je .ch2_pio_set
|
||||||
|
|
||||||
|
cmp [ebx+IDE_DEVICE.UDMA_set_mode], al
|
||||||
|
je .ch2_pio_set
|
||||||
|
;--------------------------------------
|
||||||
|
@@:
|
||||||
|
mov dx, [ecx+IDE_DATA.BAR3_val] ;0x374
|
||||||
|
add dx, 2 ;0x376
|
||||||
|
out dx, al
|
||||||
|
DEBUGF 1, "K : IDE CH2 DMA enabled\n"
|
||||||
|
mov [ecx+IDE_DATA.dma_hdd_channel_2], byte 1
|
||||||
|
;--------------------------------------
|
||||||
|
.set_interrupts_for_IDE_controllers:
|
||||||
|
mov esi, boot_set_int_IDE
|
||||||
|
call boot_log
|
||||||
|
;--------------------------------------
|
||||||
|
mov eax, [ecx+IDE_DATA.ProgrammingInterface]
|
||||||
|
cmp ax, 0x0180
|
||||||
|
je .pata_ide
|
||||||
|
|
||||||
|
cmp ax, 0x018a
|
||||||
|
jne .sata_ide
|
||||||
|
;--------------------------------------
|
||||||
|
.pata_ide:
|
||||||
|
cmp [ecx+IDE_DATA.RegsBaseAddres], 0
|
||||||
|
je .end_set_interrupts
|
||||||
|
|
||||||
|
push ecx
|
||||||
|
stdcall attach_int_handler, 14, IDE_irq_14_handler, 0
|
||||||
|
DEBUGF 1, "K : Set IDE IRQ14 return code %x\n", eax
|
||||||
|
stdcall attach_int_handler, 15, IDE_irq_15_handler, 0
|
||||||
|
DEBUGF 1, "K : Set IDE IRQ15 return code %x\n", eax
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
jmp .end_set_interrupts
|
||||||
|
;--------------------------------------
|
||||||
|
.sata_ide:
|
||||||
|
cmp ax, 0x0185
|
||||||
|
je .sata_ide_1
|
||||||
|
|
||||||
|
cmp ax, 0x018f
|
||||||
|
jne .end_set_interrupts
|
||||||
|
;--------------------------------------
|
||||||
|
.sata_ide_1:
|
||||||
|
; Some weird controllers generate an interrupt even if IDE interrupts
|
||||||
|
; are disabled and no IDE devices. For example, notebook ASUS K72F -
|
||||||
|
; IDE controller 010185 generates false interrupt when we work with
|
||||||
|
; the IDE controller 01018f. For this reason, the interrupt handler
|
||||||
|
; does not need to be installed if both channel IDE controller
|
||||||
|
; running in PIO mode.
|
||||||
|
cmp [ecx+IDE_DATA.RegsBaseAddres], 0
|
||||||
|
je .end_set_interrupts
|
||||||
|
|
||||||
|
cmp [ecx+IDE_DATA.dma_hdd_channel_1], 0
|
||||||
|
jne @f
|
||||||
|
|
||||||
|
cmp [ecx+IDE_DATA.dma_hdd_channel_2], 0
|
||||||
|
je .end_set_interrupts
|
||||||
|
;--------------------------------------
|
||||||
|
@@:
|
||||||
|
mov ax, [ecx+IDE_DATA.Interrupt]
|
||||||
|
movzx eax, al
|
||||||
|
push ecx
|
||||||
|
stdcall attach_int_handler, eax, IDE_common_irq_handler, 0
|
||||||
|
pop ecx
|
||||||
|
DEBUGF 1, "K : Set IDE IRQ%d return code %x\n", [ecx+IDE_DATA.Interrupt]:1, eax
|
||||||
|
;--------------------------------------
|
||||||
|
.end_set_interrupts:
|
||||||
|
popfd
|
||||||
|
ret
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
; END of initialisation IDE ATA code
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
find_IDE_controller_done:
|
||||||
|
mov ecx, IDE_controller_1
|
||||||
|
mov [IDE_controller_pointer], ecx
|
||||||
|
call Init_IDE_ATA_controller
|
||||||
|
mov ecx, IDE_controller_2
|
||||||
|
mov [IDE_controller_pointer], ecx
|
||||||
|
call Init_IDE_ATA_controller
|
||||||
|
mov ecx, IDE_controller_3
|
||||||
|
mov [IDE_controller_pointer], ecx
|
||||||
|
call Init_IDE_ATA_controller
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
mov esi, boot_getcache
|
||||||
|
call boot_log
|
||||||
|
include 'getcache.inc'
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
mov esi, boot_detectpart
|
||||||
|
call boot_log
|
||||||
|
include 'sear_par.inc'
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
mov esi, boot_init_sys
|
||||||
|
call boot_log
|
||||||
|
call Parser_params
|
||||||
|
|
||||||
|
if ~ defined extended_primary_loader
|
||||||
|
; ramdisk image should be loaded by extended primary loader if it exists
|
||||||
|
; READ RAMDISK IMAGE FROM HD
|
||||||
|
include '../boot/rdload.inc'
|
||||||
|
end if
|
||||||
|
;-----------------------------------------------------------------------------
|
||||||
|
mov ecx, IDE_controller_1
|
||||||
|
mov [IDE_controller_pointer], ecx
|
||||||
|
call Init_IDE_ATA_controller_2
|
||||||
|
mov ecx, IDE_controller_2
|
||||||
|
mov [IDE_controller_pointer], ecx
|
||||||
|
call Init_IDE_ATA_controller_2
|
||||||
|
mov ecx, IDE_controller_3
|
||||||
|
mov [IDE_controller_pointer], ecx
|
||||||
|
call Init_IDE_ATA_controller_2
|
||||||
|
;-----------------------------------------------------------------------------
|
@ -39,6 +39,7 @@ syscall_button: ;///// system function 8 //////////////////////////////////////
|
|||||||
;> 7 (31) = 0
|
;> 7 (31) = 0
|
||||||
;> 6 (30) = don't draw button
|
;> 6 (30) = don't draw button
|
||||||
;> 5 (29) = don't draw button frame when pressed
|
;> 5 (29) = don't draw button frame when pressed
|
||||||
|
;> 4 (28) = don't draw button 3d frame
|
||||||
;> esi = button color
|
;> esi = button color
|
||||||
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
;; Undefine button:
|
;; Undefine button:
|
||||||
@ -86,9 +87,11 @@ syscall_button: ;///// system function 8 //////////////////////////////////////
|
|||||||
mov ax, dx
|
mov ax, dx
|
||||||
stosw ; button id number: bits 0-15
|
stosw ; button id number: bits 0-15
|
||||||
mov eax, ebx
|
mov eax, ebx
|
||||||
|
dec eax
|
||||||
rol eax, 16
|
rol eax, 16
|
||||||
stosd ; x start | x size
|
stosd ; x start | x size
|
||||||
mov eax, ecx
|
mov eax, ecx
|
||||||
|
dec eax
|
||||||
rol eax, 16
|
rol eax, 16
|
||||||
stosd ; y start | y size
|
stosd ; y start | y size
|
||||||
mov eax, edx
|
mov eax, edx
|
||||||
@ -100,113 +103,115 @@ syscall_button: ;///// system function 8 //////////////////////////////////////
|
|||||||
test edx, 0x40000000
|
test edx, 0x40000000
|
||||||
jnz .exit
|
jnz .exit
|
||||||
|
|
||||||
; draw button body
|
; DRAW BODY -----------------------------
|
||||||
|
|
||||||
pushad
|
pushad
|
||||||
|
call button._.button_calc_relativ
|
||||||
; calculate window-relative coordinates
|
xor edi, edi ; for __sys_draw_line
|
||||||
movzx edi, cx
|
; set color
|
||||||
shr ebx, 16
|
|
||||||
shr ecx, 16
|
|
||||||
mov eax, [TASK_BASE]
|
|
||||||
add ebx, [eax - twdw + WDATA.box.left]
|
|
||||||
add ecx, [eax - twdw + WDATA.box.top]
|
|
||||||
mov eax, ebx
|
|
||||||
shl eax, 16
|
|
||||||
mov ax, bx
|
|
||||||
add ax, word[esp + 16]
|
|
||||||
mov ebx, ecx
|
|
||||||
shl ebx, 16
|
|
||||||
mov bx, cx
|
|
||||||
|
|
||||||
; calculate initial color
|
|
||||||
mov ecx, esi
|
mov ecx, esi
|
||||||
|
; set coordinate
|
||||||
|
inc edx
|
||||||
|
; if gradient
|
||||||
cmp [buttontype], 0
|
cmp [buttontype], 0
|
||||||
je @f
|
je .next_line
|
||||||
call button._.incecx2
|
call button._.incecx
|
||||||
|
align 4
|
||||||
; set button height counter
|
|
||||||
@@:
|
|
||||||
mov edx, edi
|
|
||||||
|
|
||||||
.next_line:
|
.next_line:
|
||||||
call button._.button_dececx
|
call button._.button_dececx
|
||||||
push edi
|
|
||||||
xor edi, edi
|
|
||||||
; call [draw_line]
|
|
||||||
call __sys_draw_line
|
call __sys_draw_line
|
||||||
pop edi
|
|
||||||
add ebx, 0x00010001
|
add ebx, 0x00010001
|
||||||
dec edx
|
dec edx
|
||||||
jnz .next_line
|
jnz .next_line
|
||||||
|
|
||||||
popad
|
popad
|
||||||
|
|
||||||
; draw button frame
|
; DRAW FRAME ----------------------------
|
||||||
|
pushad
|
||||||
|
call button._.button_calc_relativ
|
||||||
|
mov esi, common_colours
|
||||||
|
|
||||||
push ebx ecx
|
mov edi, dword [esi+104]
|
||||||
|
call .top_border
|
||||||
|
mov edi, dword [esi+104]
|
||||||
|
call .bottom_border
|
||||||
|
mov edi, dword [esi+104]
|
||||||
|
call .right_border
|
||||||
|
mov edi, dword [esi+104]
|
||||||
|
call .left_border
|
||||||
|
popad
|
||||||
|
|
||||||
; calculate window-relative coordinates
|
; DRAW 3D SHADOW ------------------------
|
||||||
shr ebx, 16
|
test edx, 0x10000000
|
||||||
shr ecx, 16
|
jnz .exit
|
||||||
mov eax, [TASK_BASE]
|
|
||||||
add ebx, [eax - twdw + WDATA.box.left]
|
|
||||||
add ecx, [eax - twdw + WDATA.box.top]
|
|
||||||
|
|
||||||
; top border
|
pushad
|
||||||
mov eax, ebx
|
mov edi, edx
|
||||||
shl eax, 16
|
call button._.button_calc_relativ
|
||||||
mov ax, bx
|
; get color address
|
||||||
add ax, [esp + 4]
|
mov esi, common_colours
|
||||||
|
test edi, 0x10000000
|
||||||
|
jnz @f
|
||||||
|
add eax, 0x10000
|
||||||
|
dec eax
|
||||||
|
inc ecx
|
||||||
|
dec edx
|
||||||
|
dec edx
|
||||||
|
align 4
|
||||||
|
@@:
|
||||||
|
mov edi, dword [esi+12]
|
||||||
|
call .top_border
|
||||||
|
mov edi, dword [esi+8]
|
||||||
|
call .bottom_border
|
||||||
|
mov edi, dword [esi+8]
|
||||||
|
call .right_border
|
||||||
|
mov edi, dword [esi+12]
|
||||||
|
call .left_border
|
||||||
|
popad
|
||||||
|
ret
|
||||||
|
|
||||||
|
align 4
|
||||||
|
.top_border:
|
||||||
mov ebx, ecx
|
mov ebx, ecx
|
||||||
shl ebx, 16
|
shl ebx, 16
|
||||||
mov bx , cx
|
mov bx , cx
|
||||||
push ebx
|
mov ecx, edi
|
||||||
xor edi, edi
|
xor edi, edi
|
||||||
mov ecx, esi
|
|
||||||
call button._.incecx
|
|
||||||
; call [draw_line]
|
|
||||||
call __sys_draw_line
|
call __sys_draw_line
|
||||||
|
ret
|
||||||
|
|
||||||
; bottom border
|
align 4
|
||||||
movzx edx, word[esp + 4 + 0]
|
.bottom_border:
|
||||||
add ebx, edx
|
add bx , dx
|
||||||
shl edx, 16
|
rol ebx, 16
|
||||||
add ebx, edx
|
add bx , dx
|
||||||
mov ecx, esi
|
mov ecx, edi
|
||||||
call button._.dececx
|
xor edi, edi
|
||||||
; call [draw_line]
|
|
||||||
call __sys_draw_line
|
call __sys_draw_line
|
||||||
|
ret
|
||||||
|
|
||||||
; left border
|
align 4
|
||||||
pop ebx
|
.right_border:
|
||||||
push edx
|
push eax
|
||||||
mov edx, eax
|
sub bx, dx
|
||||||
shr edx, 16
|
mov cx, ax
|
||||||
mov ax, dx
|
shl eax, 16
|
||||||
mov edx, ebx
|
mov ax, cx
|
||||||
shr edx, 16
|
mov ecx, edi
|
||||||
mov bx, dx
|
xor edi, edi
|
||||||
add bx, [esp + 4 + 0]
|
|
||||||
pop edx
|
|
||||||
mov ecx, esi
|
|
||||||
call button._.incecx
|
|
||||||
; call [draw_line]
|
|
||||||
call __sys_draw_line
|
call __sys_draw_line
|
||||||
|
pop eax
|
||||||
|
ret
|
||||||
|
|
||||||
; right border
|
align 4
|
||||||
mov dx, [esp + 4]
|
.left_border:
|
||||||
add ax, dx
|
shr eax, 16
|
||||||
shl edx, 16
|
mov cx, ax
|
||||||
add eax, edx
|
shl eax, 16
|
||||||
add ebx, 0x00010000
|
mov ax, cx
|
||||||
mov ecx, esi
|
mov ecx, edi
|
||||||
call button._.dececx
|
xor edi, edi
|
||||||
; call [draw_line]
|
|
||||||
call __sys_draw_line
|
call __sys_draw_line
|
||||||
|
ret
|
||||||
pop ecx ebx
|
align 4
|
||||||
|
|
||||||
.exit:
|
.exit:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@ -269,8 +274,10 @@ sys_button_activate_handler: ;/////////////////////////////////////////////////
|
|||||||
jz .exit
|
jz .exit
|
||||||
|
|
||||||
mov ebx, dword[eax + SYS_BUTTON.id_hi - 2]
|
mov ebx, dword[eax + SYS_BUTTON.id_hi - 2]
|
||||||
|
push edi ; spam
|
||||||
|
xor edi, edi
|
||||||
call button._.negative_button
|
call button._.negative_button
|
||||||
|
pop edi
|
||||||
.exit:
|
.exit:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@ -289,8 +296,11 @@ sys_button_deactivate_handler: ;///////////////////////////////////////////////
|
|||||||
jz .exit
|
jz .exit
|
||||||
|
|
||||||
mov ebx, dword[eax + SYS_BUTTON.id_hi - 2]
|
mov ebx, dword[eax + SYS_BUTTON.id_hi - 2]
|
||||||
|
push edi ; spam
|
||||||
|
xor edi, edi
|
||||||
|
inc edi
|
||||||
call button._.negative_button
|
call button._.negative_button
|
||||||
|
pop edi
|
||||||
.exit:
|
.exit:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@ -373,69 +383,6 @@ button._.find_button: ;////////////////////////////////////////////////////////
|
|||||||
pop edi esi edx ecx
|
pop edi esi edx ecx
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;------------------------------------------------------------------------------
|
|
||||||
button._.dececx: ;/////////////////////////////////////////////////////////////
|
|
||||||
;------------------------------------------------------------------------------
|
|
||||||
;? <description>
|
|
||||||
;------------------------------------------------------------------------------
|
|
||||||
sub cl, 0x20
|
|
||||||
jnc @f
|
|
||||||
xor cl, cl
|
|
||||||
@@:
|
|
||||||
sub ch, 0x20
|
|
||||||
jnc @f
|
|
||||||
xor ch, ch
|
|
||||||
@@:
|
|
||||||
rol ecx, 16
|
|
||||||
sub cl, 0x20
|
|
||||||
jnc @f
|
|
||||||
xor cl, cl
|
|
||||||
@@:
|
|
||||||
rol ecx, 16
|
|
||||||
ret
|
|
||||||
|
|
||||||
;------------------------------------------------------------------------------
|
|
||||||
button._.incecx: ;/////////////////////////////////////////////////////////////
|
|
||||||
;------------------------------------------------------------------------------
|
|
||||||
;? <description>
|
|
||||||
;------------------------------------------------------------------------------
|
|
||||||
add cl, 0x20
|
|
||||||
jnc @f
|
|
||||||
or cl, -1
|
|
||||||
@@:
|
|
||||||
add ch, 0x20
|
|
||||||
jnc @f
|
|
||||||
or ch, -1
|
|
||||||
@@:
|
|
||||||
rol ecx, 16
|
|
||||||
add cl, 0x20
|
|
||||||
jnc @f
|
|
||||||
or cl, -1
|
|
||||||
@@:
|
|
||||||
rol ecx, 16
|
|
||||||
ret
|
|
||||||
|
|
||||||
;------------------------------------------------------------------------------
|
|
||||||
button._.incecx2: ;////////////////////////////////////////////////////////////
|
|
||||||
;------------------------------------------------------------------------------
|
|
||||||
;? <description>
|
|
||||||
;------------------------------------------------------------------------------
|
|
||||||
add cl, 0x14
|
|
||||||
jnc @f
|
|
||||||
or cl, -1
|
|
||||||
@@:
|
|
||||||
add ch, 0x14
|
|
||||||
jnc @f
|
|
||||||
or ch, -1
|
|
||||||
@@:
|
|
||||||
rol ecx, 16
|
|
||||||
add cl, 0x14
|
|
||||||
jnc @f
|
|
||||||
or cl, -1
|
|
||||||
@@:
|
|
||||||
rol ecx, 16
|
|
||||||
ret
|
|
||||||
|
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
button._.button_dececx: ;//////////////////////////////////////////////////////
|
button._.button_dececx: ;//////////////////////////////////////////////////////
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
@ -446,9 +393,9 @@ button._.button_dececx: ;//////////////////////////////////////////////////////
|
|||||||
|
|
||||||
push eax
|
push eax
|
||||||
mov al, 1
|
mov al, 1
|
||||||
cmp edi, 20
|
;cmp edi, 20
|
||||||
jg @f
|
;jg @f
|
||||||
mov al, 2
|
;mov al, 2
|
||||||
|
|
||||||
@@:
|
@@:
|
||||||
sub cl, al
|
sub cl, al
|
||||||
@ -470,18 +417,60 @@ button._.button_dececx: ;//////////////////////////////////////////////////////
|
|||||||
|
|
||||||
.finish:
|
.finish:
|
||||||
ret
|
ret
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
button._.incecx: ;////////////////////////////////////////////////////////////
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
;? <description>
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
add cl, 0x14
|
||||||
|
jnc @f
|
||||||
|
or cl, -1
|
||||||
|
@@:
|
||||||
|
add ch, 0x14
|
||||||
|
jnc @f
|
||||||
|
or ch, -1
|
||||||
|
@@:
|
||||||
|
rol ecx, 16
|
||||||
|
add cl, 0x14
|
||||||
|
jnc @f
|
||||||
|
or cl, -1
|
||||||
|
@@:
|
||||||
|
rol ecx, 16
|
||||||
|
ret
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
button._.button_calc_relativ: ;
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
;? <description>
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
movzx edx, cx
|
||||||
|
dec edx ; get height
|
||||||
|
shr ebx, 16
|
||||||
|
shr ecx, 16
|
||||||
|
mov eax, [TASK_BASE]
|
||||||
|
add ebx, [eax - twdw + WDATA.box.left]
|
||||||
|
add ecx, [eax - twdw + WDATA.box.top]
|
||||||
|
mov eax, ebx
|
||||||
|
shl eax, 16
|
||||||
|
mov ax, bx
|
||||||
|
add ax, word[esp + 20]
|
||||||
|
dec eax
|
||||||
|
mov bx, cx
|
||||||
|
shl ebx, 16
|
||||||
|
mov bx, cx
|
||||||
|
ret
|
||||||
|
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
button._.negative_button: ;////////////////////////////////////////////////////
|
button._.negative_button: ;////////////////////////////////////////////////////
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
;? Invert system button border
|
;? Invert system button border
|
||||||
|
; edi - 0 activate, 1 - deactivate
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
; if requested, do not display button border on press.
|
; if requested, do not display button border on press.
|
||||||
test ebx, 0x20000000
|
test ebx, 0x20000000
|
||||||
jnz .exit
|
jnz .exit
|
||||||
|
|
||||||
pushad
|
pushad
|
||||||
|
push ebx
|
||||||
xchg esi, eax
|
xchg esi, eax
|
||||||
|
|
||||||
movzx ecx, [esi + SYS_BUTTON.pslot]
|
movzx ecx, [esi + SYS_BUTTON.pslot]
|
||||||
@ -499,10 +488,58 @@ button._.negative_button: ;////////////////////////////////////////////////////
|
|||||||
add ax, cx
|
add ax, cx
|
||||||
add bx, dx
|
add bx, dx
|
||||||
|
|
||||||
|
xor edx, edx
|
||||||
|
mov dx, [esi + SYS_BUTTON.id_lo]
|
||||||
|
|
||||||
|
cmp dx, 1
|
||||||
|
jne .no_close
|
||||||
|
sub eax, 0x00010001
|
||||||
|
dec ebx
|
||||||
mov esi, 0x01000000
|
mov esi, 0x01000000
|
||||||
call draw_rectangle.forced
|
call draw_rectangle.forced
|
||||||
|
jmp .fade
|
||||||
|
align 4
|
||||||
|
.no_close:
|
||||||
|
cmp dx, 65535
|
||||||
|
jne .no_mini
|
||||||
|
sub eax, 0x00010001
|
||||||
|
dec ebx
|
||||||
|
mov esi, 0x01000000
|
||||||
|
call draw_rectangle.forced
|
||||||
|
jmp .fade
|
||||||
|
align 4
|
||||||
|
.no_mini:
|
||||||
|
add eax, 0x00010000
|
||||||
|
add ebx, 0x00010000
|
||||||
|
pop edx
|
||||||
|
test edx, 0x10000000
|
||||||
|
jnz .only_frame
|
||||||
|
mov edx, common_colours
|
||||||
|
mov esi, dword [edx+12]
|
||||||
|
cmp edi, 0
|
||||||
|
jne .shadow
|
||||||
|
mov esi, dword [edx+8]
|
||||||
|
align 4
|
||||||
|
.shadow:
|
||||||
|
call draw_rectangle.forced
|
||||||
|
align 4
|
||||||
|
.only_frame:
|
||||||
|
mov edx, common_colours
|
||||||
|
sub eax, 0x00010000
|
||||||
|
sub ebx, 0x00010000
|
||||||
|
mov esi, dword [edx+104]
|
||||||
|
cmp edi, 0
|
||||||
|
jne .draw
|
||||||
|
mov esi, dword [edx+112]
|
||||||
|
align 4
|
||||||
|
.draw:
|
||||||
|
call draw_rectangle.forced
|
||||||
popad
|
popad
|
||||||
|
ret
|
||||||
|
align 4
|
||||||
|
.fade:
|
||||||
|
pop ebx
|
||||||
|
popad
|
||||||
|
align 4
|
||||||
.exit:
|
.exit:
|
||||||
ret
|
ret
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
|
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
|
||||||
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
|
;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;;
|
||||||
;; Distributed under terms of the GNU General Public License ;;
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@ -457,19 +457,40 @@ send_scancode:
|
|||||||
test bl, bl
|
test bl, bl
|
||||||
jz .exit.irq1
|
jz .exit.irq1
|
||||||
|
|
||||||
|
cmp cl, 0xE0 ; extended keycode
|
||||||
|
jne @f
|
||||||
|
|
||||||
|
cmp ch, 53
|
||||||
|
jne .dowrite
|
||||||
|
|
||||||
|
mov bl, '/'
|
||||||
|
jmp .dowrite
|
||||||
|
@@:
|
||||||
|
|
||||||
|
cmp ch, 55
|
||||||
|
jne @f
|
||||||
|
|
||||||
|
mov bl, '*'
|
||||||
|
jmp .dowrite
|
||||||
|
@@:
|
||||||
|
|
||||||
|
cmp ch, 74
|
||||||
|
jne @f
|
||||||
|
|
||||||
|
mov bl, '-'
|
||||||
|
jmp .dowrite
|
||||||
|
@@:
|
||||||
|
|
||||||
|
cmp ch, 78
|
||||||
|
jne @f
|
||||||
|
|
||||||
|
mov bl, '+'
|
||||||
|
jmp .dowrite
|
||||||
|
@@:
|
||||||
|
|
||||||
test [kb_state], VKEY_NUMLOCK
|
test [kb_state], VKEY_NUMLOCK
|
||||||
jz .dowrite
|
jz .dowrite
|
||||||
|
|
||||||
cmp cl, 0xE0
|
|
||||||
jz .dowrite
|
|
||||||
|
|
||||||
cmp ch, 55
|
|
||||||
jnz @f
|
|
||||||
|
|
||||||
mov bl, 0x2A ;*
|
|
||||||
jmp .dowrite
|
|
||||||
;--------------------------------------
|
|
||||||
@@:
|
|
||||||
cmp ch, 71
|
cmp ch, 71
|
||||||
jb .dowrite
|
jb .dowrite
|
||||||
|
|
||||||
|
@ -685,7 +685,8 @@ no_mode_0x12:
|
|||||||
|
|
||||||
xchg bx, bx
|
xchg bx, bx
|
||||||
|
|
||||||
call v86_init
|
; call v86_init
|
||||||
|
call init_sys_v86
|
||||||
|
|
||||||
mov esi, boot_inittimer
|
mov esi, boot_inittimer
|
||||||
call boot_log
|
call boot_log
|
||||||
@ -1008,7 +1009,6 @@ endg
|
|||||||
; Load PS/2 mouse driver
|
; Load PS/2 mouse driver
|
||||||
|
|
||||||
stdcall load_driver, szPS2MDriver
|
stdcall load_driver, szPS2MDriver
|
||||||
; stdcall load_driver, szCOM_MDriver
|
|
||||||
|
|
||||||
mov esi, boot_setmouse
|
mov esi, boot_setmouse
|
||||||
call boot_log
|
call boot_log
|
||||||
|
@ -267,10 +267,9 @@ IPv4_input: ; TODO: add IPv4
|
|||||||
cmp eax, 224
|
cmp eax, 224
|
||||||
je .ip_ok
|
je .ip_ok
|
||||||
|
|
||||||
; or a loopback address (127.0.0.0/8)
|
; maybe we just dont have an IP yet and should accept everything on the IP level
|
||||||
|
|
||||||
and eax, 0x00ffffff
|
cmp [IP_LIST + edi], 0
|
||||||
cmp eax, 127
|
|
||||||
je .ip_ok
|
je .ip_ok
|
||||||
|
|
||||||
; or it's just not meant for us.. :(
|
; or it's just not meant for us.. :(
|
||||||
|
@ -110,7 +110,7 @@ SS_MORETOCOME = 0x4000
|
|||||||
SS_BLOCKED = 0x8000
|
SS_BLOCKED = 0x8000
|
||||||
|
|
||||||
|
|
||||||
SOCKET_MAXDATA = 4096*8 ; must be 4096*(power of 2) where 'power of 2' is at least 8
|
SOCKET_MAXDATA = 4096*64 ; must be 4096*(power of 2) where 'power of 2' is at least 8
|
||||||
MAX_backlog = 20 ; maximum backlog for stream sockets
|
MAX_backlog = 20 ; maximum backlog for stream sockets
|
||||||
|
|
||||||
; Error Codes
|
; Error Codes
|
||||||
|
Loading…
Reference in New Issue
Block a user