diff --git a/kernel/branches/kolibri-process/blkdev/disk.inc b/kernel/branches/kolibri-process/blkdev/disk.inc index f9036a67c4..0949c0d8b6 100644 --- a/kernel/branches/kolibri-process/blkdev/disk.inc +++ b/kernel/branches/kolibri-process/blkdev/disk.inc @@ -5,7 +5,7 @@ ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -$Revision: 4273 $ +$Revision: 4437 $ ; ============================================================================= ; ================================= Constants ================================= diff --git a/kernel/branches/kolibri-process/blkdev/disk_cache.inc b/kernel/branches/kolibri-process/blkdev/disk_cache.inc index ba1e785d76..43570c03fe 100644 --- a/kernel/branches/kolibri-process/blkdev/disk_cache.inc +++ b/kernel/branches/kolibri-process/blkdev/disk_cache.inc @@ -5,7 +5,7 @@ ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -$Revision: 4133 $ +$Revision: 4465 $ ; Read/write functions try to do large operations, ; it is significantly faster than several small operations. diff --git a/kernel/branches/kolibri-process/blkdev/flp_drv.inc b/kernel/branches/kolibri-process/blkdev/flp_drv.inc index f461435164..8d5d2246ab 100644 --- a/kernel/branches/kolibri-process/blkdev/flp_drv.inc +++ b/kernel/branches/kolibri-process/blkdev/flp_drv.inc @@ -5,7 +5,7 @@ ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -$Revision: 4273 $ +$Revision: 4695 $ ;********************************************************** diff --git a/kernel/branches/kolibri-process/blkdev/hd_drv.inc b/kernel/branches/kolibri-process/blkdev/hd_drv.inc index 61693e6525..d066ddbc8b 100644 --- a/kernel/branches/kolibri-process/blkdev/hd_drv.inc +++ b/kernel/branches/kolibri-process/blkdev/hd_drv.inc @@ -5,7 +5,7 @@ ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -$Revision: 4420 $ +$Revision: 4839 $ ; Low-level driver for HDD access diff --git a/kernel/branches/kolibri-process/blkdev/ide_cache.inc b/kernel/branches/kolibri-process/blkdev/ide_cache.inc index 5903b76f0c..d490f3594b 100644 --- a/kernel/branches/kolibri-process/blkdev/ide_cache.inc +++ b/kernel/branches/kolibri-process/blkdev/ide_cache.inc @@ -21,7 +21,7 @@ ; ;************************************************************************** -$Revision: 3742 $ +$Revision: 4700 $ align 4 find_empty_slot_CD_cache: diff --git a/kernel/branches/kolibri-process/core/exports.inc b/kernel/branches/kolibri-process/core/exports.inc index 0eb8cd3131..7a8ddaa89f 100644 --- a/kernel/branches/kolibri-process/core/exports.inc +++ b/kernel/branches/kolibri-process/core/exports.inc @@ -94,6 +94,7 @@ __exports: load_cursor, 'LoadCursor', \ ;stdcall \ get_curr_task, 'GetCurrentTask', \ + change_task, 'ChangeTask', \ load_file, 'LoadFile', \ ;retval eax, ebx delay_ms, 'Sleep', \ \ diff --git a/kernel/branches/kolibri-process/core/mtrr.inc b/kernel/branches/kolibri-process/core/mtrr.inc new file mode 100644 index 0000000000..df3507bbc5 --- /dev/null +++ b/kernel/branches/kolibri-process/core/mtrr.inc @@ -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 diff --git a/kernel/branches/kolibri-process/core/v86.inc b/kernel/branches/kolibri-process/core/v86.inc index deddde18e4..483b1aa8d1 100644 --- a/kernel/branches/kolibri-process/core/v86.inc +++ b/kernel/branches/kolibri-process/core/v86.inc @@ -14,9 +14,7 @@ DEBUG_SHOW_IO = 0 struct V86_machine ; page directory - pagedir dd ? -; translation table: V86 address -> flat linear address - pages dd ? + process dd ? ; mutex to protect all data from writing by multiple threads at one time mutex dd ? ; i/o permission map @@ -38,91 +36,87 @@ v86_create: and dword [eax+V86_machine.mutex], 0 ; allocate tables mov ebx, eax -; We allocate 4 pages. -; First is main page directory for V86 mode. -; Second page: -; first half (0x800 bytes) is page table for addresses 0 - 0x100000, -; second half is for V86-to-linear translation. -; Third and fourth are for I/O permission map. - push 8000h ; blocks less than 8 pages are discontinuous + + stdcall create_process, 4096, OS_BASE, 4096 + test eax, eax + jz .fail2 + + mov [eax+PROC.mem_used], 4096 + mov [ebx+V86_machine.process], eax + + push 2000h call kernel_alloc test eax, eax jz .fail2 - mov [ebx+V86_machine.pagedir], eax - push edi eax - mov edi, eax - add eax, 1800h - mov [ebx+V86_machine.pages], eax + + mov [ebx+V86_machine.iopm], eax + + ; initialize tables - mov ecx, 2000h/4 - 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... + push edi mov edi, eax - add eax, 1000h - push eax - call get_pg_addr - or al, PG_UW - stosd -; ...and also copy system page tables -; thx to Serge, system is located at high addresses - add edi, (OS_BASE shr 20) - 4 - push esi - mov esi, sys_proc+PROC.pdt_0+(OS_BASE shr 20) - mov ecx, 0x80000000 shr 22 - rep movsd + mov eax, -1 + mov ecx, 2000h/4 + rep stosd + + mov eax, [ebx+V86_machine.process] + mov eax, [eax+PROC.pdt_0_phys] + + pushfd + cli + mov cr3, eax - 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 - pop eax + ; first page - BIOS data (shared between all machines!) ; physical address = 0 ; 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!) ; physical address = 0x9C000 ; linear address = 0x8009C000 ; (I have seen one computer with EBDA segment = 0x9D80, ; all other computers use less memory) - mov ecx, 4 - mov edx, 0x9C000 - push eax - lea edi, [eax+0x9C*4] + + mov eax, PG_UW + mov [page_tabs], eax + 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 - add edx, 0x1000 - loop @b - pop eax - pop edi + add eax, edx + loop @b + ; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!) ; 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 - shl edx, 12 - push edx - or edx, 111b - mov [eax+ecx*4], edx - pop edx - add edx, OS_BASE - mov [eax+ecx*4+0x800], edx - inc cl - jnz @b + stosd + add eax, edx + loop @b + + mov eax, sys_proc-OS_BASE+PROC.pdt_0 + + mov cr3, eax + popfd + + pop edi + mov eax, ebx ret .fail2: @@ -132,15 +126,16 @@ v86_create: xor eax, eax ret +;not used ; Destroy V86 machine ; in: eax = handle ; out: nothing ; destroys: eax, ebx, ecx, edx (due to free) -v86_destroy: - push eax - stdcall kernel_free, [eax+V86_machine.pagedir] - pop eax - jmp free +;v86_destroy: +; push eax +; stdcall kernel_free, [eax+V86_machine.pagedir] +; pop eax +; jmp free ; Translate V86-address to linear address ; in: eax=V86 address @@ -150,28 +145,29 @@ v86_destroy: v86_get_lin_addr: push ecx edx mov ecx, eax - mov edx, [esi+V86_machine.pages] + mov edx, page_tabs shr ecx, 12 and eax, 0xFFF add eax, [edx+ecx*4] ; atomic operation, no mutex needed pop edx ecx ret +;not used ; Sets linear address for V86-page ; in: eax=linear address (must be page-aligned) ; ecx=V86 page (NOT address!) ; esi=handle ; out: nothing ; destroys: nothing -v86_set_page: - push eax ebx - mov ebx, [esi+V86_machine.pagedir] - mov [ebx+ecx*4+0x1800], eax - call get_pg_addr - or al, 111b - mov [ebx+ecx*4+0x1000], eax - pop ebx eax - ret +;v86_set_page: +; push eax ebx +; mov ebx, [esi+V86_machine.pagedir] +; mov [ebx+ecx*4+0x1800], eax +; call get_pg_addr +; or al, 111b +; mov [ebx+ecx*4+0x1000], eax +; pop ebx eax +; ret ; Allocate memory in V86 machine ; in: eax=size (in bytes) @@ -214,21 +210,7 @@ init_sys_v86: mov [sys_v86_machine], eax test eax, eax 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 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 ; allow access to all ports mov ecx, [esi+V86_machine.iopm] @@ -272,6 +254,9 @@ ends ; eax = 3 - IRQ is already hooked by another VM ; destroys: nothing v86_start: + + xchg bx, bx + pushad cli @@ -296,12 +281,10 @@ v86_start: mov [ecx+APPDATA.saved_esp0], esp mov [tss._esp0], esp - mov eax, [esi+V86_machine.pagedir] - call get_pg_addr + mov eax, [esi+V86_machine.process] mov [ecx+APPDATA.process], eax -; mov cr3, eax - -; mov [irq_tab+5*4], my05 + mov eax, [eax+PROC.pdt_0_phys] + mov cr3, eax ; We do not enable interrupts, because V86 IRQ redirector assumes that ; machine is running @@ -795,6 +778,7 @@ end if pop ebx mov dword [SLOT_BASE+ecx+APPDATA.io_map], ebx mov dword [page_tabs + (tss._io_map_0 shr 10)], ebx + mov eax, [eax+PROC.pdt_0_phys] mov cr3, eax sti @@ -843,8 +827,7 @@ v86_irq: pop eax v86_irq2: mov esi, [v86_irqhooks+edi*8] ; get VM handle - mov eax, [esi+V86_machine.pagedir] - call get_pg_addr + mov eax, [esi+V86_machine.process] mov ecx, [CURRENT_TASK] shl ecx, 8 cmp [SLOT_BASE+ecx+APPDATA.process], eax @@ -895,6 +878,7 @@ v86_irq2: popad iretd .found: + mov eax, [eax+PROC.pdt_0_phys] mov cr3, eax mov esi, [ebx+APPDATA.saved_esp0] sub word [esi-sizeof.v86_regs+v86_regs.esp], 6 diff --git a/kernel/branches/kolibri-process/detect/init_ata.inc b/kernel/branches/kolibri-process/detect/init_ata.inc new file mode 100644 index 0000000000..89a6242fc3 --- /dev/null +++ b/kernel/branches/kolibri-process/detect/init_ata.inc @@ -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 +;----------------------------------------------------------------------------- diff --git a/kernel/branches/kolibri-process/gui/button.inc b/kernel/branches/kolibri-process/gui/button.inc index 511a16b7b7..c64a8a066c 100644 --- a/kernel/branches/kolibri-process/gui/button.inc +++ b/kernel/branches/kolibri-process/gui/button.inc @@ -39,6 +39,7 @@ syscall_button: ;///// system function 8 ////////////////////////////////////// ;> 7 (31) = 0 ;> 6 (30) = don't draw button ;> 5 (29) = don't draw button frame when pressed +;> 4 (28) = don't draw button 3d frame ;> esi = button color ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;; Undefine button: @@ -86,9 +87,11 @@ syscall_button: ;///// system function 8 ////////////////////////////////////// mov ax, dx stosw ; button id number: bits 0-15 mov eax, ebx + dec eax rol eax, 16 stosd ; x start | x size mov eax, ecx + dec eax rol eax, 16 stosd ; y start | y size mov eax, edx @@ -100,114 +103,116 @@ syscall_button: ;///// system function 8 ////////////////////////////////////// test edx, 0x40000000 jnz .exit - ; draw button body - + ; DRAW BODY ----------------------------- pushad - - ; calculate window-relative coordinates - movzx edi, cx - 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 + call button._.button_calc_relativ + xor edi, edi ; for __sys_draw_line + ; set color mov ecx, esi + ; set coordinate + inc edx + ; if gradient cmp [buttontype], 0 - je @f - call button._.incecx2 - - ; set button height counter - @@: - mov edx, edi - - .next_line: + je .next_line + call button._.incecx +align 4 +.next_line: call button._.button_dececx - push edi - xor edi, edi -; call [draw_line] call __sys_draw_line - pop edi add ebx, 0x00010001 dec edx jnz .next_line - 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 - shr ebx, 16 - shr ecx, 16 - mov eax, [TASK_BASE] - add ebx, [eax - twdw + WDATA.box.left] - add ecx, [eax - twdw + WDATA.box.top] + ; DRAW 3D SHADOW ------------------------ + test edx, 0x10000000 + jnz .exit - ; top border - mov eax, ebx - shl eax, 16 - mov ax, bx - add ax, [esp + 4] + pushad + mov edi, edx + call button._.button_calc_relativ + ; get color address + 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 shl ebx, 16 - mov bx, cx - push ebx + mov bx , cx + mov ecx, edi xor edi, edi - mov ecx, esi - call button._.incecx -; call [draw_line] call __sys_draw_line + ret - ; bottom border - movzx edx, word[esp + 4 + 0] - add ebx, edx - shl edx, 16 - add ebx, edx - mov ecx, esi - call button._.dececx -; call [draw_line] +align 4 +.bottom_border: + add bx , dx + rol ebx, 16 + add bx , dx + mov ecx, edi + xor edi, edi call __sys_draw_line + ret - ; left border - pop ebx - push edx - mov edx, eax - shr edx, 16 - mov ax, dx - mov edx, ebx - shr edx, 16 - mov bx, dx - add bx, [esp + 4 + 0] - pop edx - mov ecx, esi - call button._.incecx -; call [draw_line] +align 4 +.right_border: + push eax + sub bx, dx + mov cx, ax + shl eax, 16 + mov ax, cx + mov ecx, edi + xor edi, edi call __sys_draw_line + pop eax + ret - ; right border - mov dx, [esp + 4] - add ax, dx - shl edx, 16 - add eax, edx - add ebx, 0x00010000 - mov ecx, esi - call button._.dececx -; call [draw_line] +align 4 +.left_border: + shr eax, 16 + mov cx, ax + shl eax, 16 + mov ax, cx + mov ecx, edi + xor edi, edi call __sys_draw_line - - pop ecx ebx - - .exit: + ret +align 4 +.exit: ret ; FIXME: mutex needed @@ -269,8 +274,10 @@ sys_button_activate_handler: ;///////////////////////////////////////////////// jz .exit mov ebx, dword[eax + SYS_BUTTON.id_hi - 2] + push edi ; spam + xor edi, edi call button._.negative_button - + pop edi .exit: ret @@ -289,8 +296,11 @@ sys_button_deactivate_handler: ;/////////////////////////////////////////////// jz .exit mov ebx, dword[eax + SYS_BUTTON.id_hi - 2] + push edi ; spam + xor edi, edi + inc edi call button._.negative_button - + pop edi .exit: ret @@ -373,69 +383,6 @@ button._.find_button: ;//////////////////////////////////////////////////////// pop edi esi edx ecx ret -;------------------------------------------------------------------------------ -button._.dececx: ;///////////////////////////////////////////////////////////// -;------------------------------------------------------------------------------ -;? -;------------------------------------------------------------------------------ - 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: ;///////////////////////////////////////////////////////////// -;------------------------------------------------------------------------------ -;? -;------------------------------------------------------------------------------ - 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: ;//////////////////////////////////////////////////////////// -;------------------------------------------------------------------------------ -;? -;------------------------------------------------------------------------------ - 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: ;////////////////////////////////////////////////////// ;------------------------------------------------------------------------------ @@ -446,9 +393,9 @@ button._.button_dececx: ;////////////////////////////////////////////////////// push eax mov al, 1 - cmp edi, 20 - jg @f - mov al, 2 + ;cmp edi, 20 + ;jg @f + ;mov al, 2 @@: sub cl, al @@ -470,18 +417,60 @@ button._.button_dececx: ;////////////////////////////////////////////////////// .finish: ret +;------------------------------------------------------------------------------ +button._.incecx: ;//////////////////////////////////////////////////////////// +;------------------------------------------------------------------------------ +;? +;------------------------------------------------------------------------------ + 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: ; +;------------------------------------------------------------------------------ +;? +;------------------------------------------------------------------------------ + 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: ;//////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;? Invert system button border +; edi - 0 activate, 1 - deactivate ;------------------------------------------------------------------------------ ; if requested, do not display button border on press. test ebx, 0x20000000 jnz .exit pushad - + push ebx xchg esi, eax movzx ecx, [esi + SYS_BUTTON.pslot] @@ -499,10 +488,58 @@ button._.negative_button: ;//////////////////////////////////////////////////// add ax, cx 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 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 - - .exit: + ret +align 4 +.fade: + pop ebx + popad +align 4 +.exit: ret diff --git a/kernel/branches/kolibri-process/hid/keyboard.inc b/kernel/branches/kolibri-process/hid/keyboard.inc index f4e0cf088e..15953679a4 100644 --- a/kernel/branches/kolibri-process/hid/keyboard.inc +++ b/kernel/branches/kolibri-process/hid/keyboard.inc @@ -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 ;; ;; Distributed under terms of the GNU General Public License ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -457,19 +457,40 @@ send_scancode: test bl, bl jz .exit.irq1 - test [kb_state], VKEY_NUMLOCK - jz .dowrite + cmp cl, 0xE0 ; extended keycode + jne @f + + cmp ch, 53 + jne .dowrite - cmp cl, 0xE0 - jz .dowrite + mov bl, '/' + jmp .dowrite +@@: cmp ch, 55 - jnz @f + jne @f - mov bl, 0x2A ;* + 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 + jz .dowrite + cmp ch, 71 jb .dowrite diff --git a/kernel/branches/kolibri-process/kernel.asm b/kernel/branches/kolibri-process/kernel.asm index 54712bbfda..bd4680d244 100644 --- a/kernel/branches/kolibri-process/kernel.asm +++ b/kernel/branches/kolibri-process/kernel.asm @@ -685,7 +685,8 @@ no_mode_0x12: xchg bx, bx - call v86_init +; call v86_init + call init_sys_v86 mov esi, boot_inittimer call boot_log @@ -1008,7 +1009,6 @@ endg ; Load PS/2 mouse driver stdcall load_driver, szPS2MDriver -; stdcall load_driver, szCOM_MDriver mov esi, boot_setmouse call boot_log diff --git a/kernel/branches/kolibri-process/network/IPv4.inc b/kernel/branches/kolibri-process/network/IPv4.inc index b3c582486d..17ce46b9e8 100644 --- a/kernel/branches/kolibri-process/network/IPv4.inc +++ b/kernel/branches/kolibri-process/network/IPv4.inc @@ -267,10 +267,9 @@ IPv4_input: ; TODO: add IPv4 cmp eax, 224 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 eax, 127 + cmp [IP_LIST + edi], 0 je .ip_ok ; or it's just not meant for us.. :( diff --git a/kernel/branches/kolibri-process/network/stack.inc b/kernel/branches/kolibri-process/network/stack.inc index 3900729399..1eb3f673c0 100644 --- a/kernel/branches/kolibri-process/network/stack.inc +++ b/kernel/branches/kolibri-process/network/stack.inc @@ -110,7 +110,7 @@ SS_MORETOCOME = 0x4000 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 ; Error Codes