From 393a43c2ba83a1bebb32a4bb56414c1e21a0abea Mon Sep 17 00:00:00 2001 From: "Evgeny Grechnikov (Diamond)" Date: Wed, 27 Sep 2006 14:58:51 +0000 Subject: [PATCH] DMA access to HD git-svn-id: svn://kolibrios.org@160 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/trunk/blkdev/hd_drv.inc | 854 +++++++++++++++++++++++++++++++++ kernel/trunk/boot/bootcode.inc | 40 ++ kernel/trunk/core/sys32.inc | 25 +- kernel/trunk/fs/fat32.inc | 459 ------------------ kernel/trunk/kernel.asm | 4 + kernel/trunk/kernel32.inc | 3 + 6 files changed, 923 insertions(+), 462 deletions(-) create mode 100755 kernel/trunk/blkdev/hd_drv.inc diff --git a/kernel/trunk/blkdev/hd_drv.inc b/kernel/trunk/blkdev/hd_drv.inc new file mode 100755 index 0000000000..c10b9db4c4 --- /dev/null +++ b/kernel/trunk/blkdev/hd_drv.inc @@ -0,0 +1,854 @@ + +;************************************************************************** +; +; 0x600008 - first entry in cache list +; +; +0 - lba sector +; +4 - state of cache sector +; 0 = empty +; 1 = used for read ( same as in hd ) +; 2 = used for write ( differs from hd ) +; +; +65536 - cache entries +; +;************************************************************************** + +align 4 +hd_read: +;----------------------------------------------------------- +; input : eax = block to read +; ebx = destination +;----------------------------------------------------------- + push ecx esi edi ; scan cache + + mov ecx,cache_max ; entries in cache + mov esi,0x600000+8 + mov edi,1 + + hdreadcache: + + cmp dword [esi+4],0 ; empty + je nohdcache + + cmp [esi],eax ; correct sector + je yeshdcache + + nohdcache: + + add esi,8 + inc edi + dec ecx + jnz hdreadcache + + call find_empty_slot ; ret in edi + cmp [hd_error],0 + jne return_01 + cmp [dma_hdd], 1 + jnz .nodma + call hd_read_dma + jmp @f +.nodma: + call hd_read_pio +@@: + + lea esi,[edi*8+0x600000] + mov [esi],eax ; sector number + mov dword [esi+4],1 ; hd read - mark as same as in hd + + yeshdcache: + + mov esi,edi + shl esi,9 + add esi,0x600000+65536 + mov edi,ebx + mov ecx,512/4 + cld + rep movsd ; move data + return_01: + pop edi esi ecx + ret + +align 4 +hd_read_pio: + push eax edx + + call disable_ide_int + + call wait_for_hd_idle + cmp [hd_error],0 + jne hd_read_error + +; cli + xor eax,eax + mov edx,[hdbase] + inc edx + out dx,al ; ATAFeatures регистр "особенностей" + inc edx + inc eax + out dx,al ; ATASectorCount счётчик секторов + inc edx + mov eax,[esp+4] + out dx,al ; ATASectorNumber регистр номера сектора + shr eax,8 + inc edx + out dx,al ; ATACylinder номер цилиндра (младший байт) + shr eax,8 + inc edx + out dx,al ; номер цилиндра (старший байт) + shr eax,8 + inc edx + and al,1+2+4+8 + add al,byte [hdid] + add al,128+64+32 + out dx,al ; номер головки/номер диска + inc edx + mov al,20h + out dx,al ; ATACommand регистр команд +; sti + + call wait_for_sector_buffer + + cmp [hd_error],0 + jne hd_read_error + +; cli + push edi + shl edi,9 + add edi,0x600000+65536 + mov ecx,256 + mov edx,[hdbase] + cld + rep insw + pop edi +; sti + + call enable_ide_int + + pop edx eax + ret + +disable_ide_int: + mov edx,[hdbase] + add edx,0x206 + mov al,2 + out dx,al + ret + +enable_ide_int: + mov edx,[hdbase] + add edx,0x206 + mov al,0 + out dx,al + ret + +align 4 +hd_write: +;----------------------------------------------------------- +; input : eax = block +; ebx = pointer to memory +;----------------------------------------------------------- + push ecx esi edi + + ; check if the cache already has the sector and overwrite it + + mov ecx,cache_max + mov esi,0x600000+8 + mov edi,1 + + hdwritecache: + + cmp dword [esi+4],0 ; if cache slot is empty + je not_in_cache_write + + cmp [esi],eax ; if the slot has the sector + je yes_in_cache_write + + not_in_cache_write: + + add esi,8 + inc edi + dec ecx + jnz hdwritecache + + ; sector not found in cache + ; write the block to a new location + + call find_empty_slot ; ret in edi + cmp [hd_error],0 + jne hd_write_access_denied + + lea esi,[edi*8+0x600000] + mov [esi],eax ; sector number + + yes_in_cache_write: + + mov dword [esi+4],2 ; write - differs from hd + + shl edi,9 + add edi,0x600000+65536 + mov esi,ebx + mov ecx,512/4 + cld + rep movsd ; move data + hd_write_access_denied: + pop edi esi ecx + ret + + +write_cache: +;----------------------------------------------------------- +; write all changed sectors to disk +;----------------------------------------------------------- + push eax ecx edx esi edi + + ; write difference ( 2 ) from cache to hd + + mov ecx,cache_max + mov esi,0x600000+8 + mov edi,1 + + write_cache_more: + + cmp dword [esi+4],2 ; if cache slot is not different + jne .write_chain + + mov dword [esi+4],1 ; same as in hd + mov eax,[esi] ; eax = sector to write + + cmp eax,[PARTITION_START] + jb danger + cmp eax,[PARTITION_END] + ja danger + + cmp [dma_hdd], 1 + jnz .nodma +; Объединяем запись цепочки последовательных секторов в одно обращение к диску + cmp ecx, 1 + jz .nonext + cmp dword [esi+8+4], 2 + jnz .nonext + push eax + inc eax + cmp eax, [esi+8] + pop eax + jnz .nonext + cmp [cache_chain_started], 1 + jz @f + mov [cache_chain_started], 1 + mov [cache_chain_size], 0 + mov [cache_chain_pos], edi + mov [cache_chain_ptr], esi +@@: + inc [cache_chain_size] + cmp [cache_chain_size], 64 + jnz .continue + jmp .write_chain +.nonext: + call flush_cache_chain + mov [cache_chain_size], 1 + mov [cache_chain_ptr], esi + call write_cache_sector + jmp .continue +.nodma: + call cache_write_pio +.write_chain: + call flush_cache_chain + +.continue: + danger: + + add esi,8 + inc edi + dec ecx + jnz write_cache_more + call flush_cache_chain + return_02: + pop edi esi edx ecx eax + ret + +flush_cache_chain: + cmp [cache_chain_started], 0 + jz @f + call write_cache_chain + mov [cache_chain_started], 0 +@@: + ret + +align 4 +cache_write_pio: + call disable_ide_int + + call wait_for_hd_idle + cmp [hd_error],0 + jne hd_write_error + +; cli + xor eax,eax + mov edx,[hdbase] + inc edx + out dx,al + inc edx + inc eax + out dx,al + inc edx + mov eax,[esi] ; eax = sector to write + out dx,al + shr eax,8 + inc edx + out dx,al + shr eax,8 + inc edx + out dx,al + shr eax,8 + inc edx + and al,1+2+4+8 + add al,byte [hdid] + add al,128+64+32 + out dx,al + inc edx + mov al,30h + out dx,al +; sti + + call wait_for_sector_buffer + + cmp [hd_error],0 + jne hd_write_error + + push ecx esi + +; cli + mov esi,edi + shl esi,9 + add esi,0x600000+65536 ; esi = from memory position + mov ecx,256 + mov edx,[hdbase] + cld + rep outsw +; sti + + call enable_ide_int + pop esi ecx + + ret + +align 4 +find_empty_slot: +;----------------------------------------------------------- +; find empty or read slot, flush cache if next 10% is used by write +; output : edi = cache slot +;----------------------------------------------------------- +; push ecx esi + + search_again: + + mov ecx,cache_max*10/100 + mov edi,[cache_search_start] + + search_for_empty: + + inc edi + cmp edi,cache_max + jbe inside_cache + mov edi,1 + + inside_cache: + + cmp dword [edi*8+0x600000+4],2 ; get cache slot info + jb found_slot ; it's empty or read + dec ecx + jnz search_for_empty + + call write_cache ; no empty slots found, write all + cmp [hd_error],0 + jne found_slot_access_denied + + jmp search_again ; and start again + + found_slot: + + mov [cache_search_start],edi + found_slot_access_denied: + ret + +align 4 +clear_hd_cache: + + push eax ecx edi + mov edi,0x600000 + mov ecx,16384 + xor eax,eax + cld + rep stosd ; clear hd cache with 0 + mov [cache_search_start],eax + mov [fat_in_cache],-1 + mov [fat_change],0 + pop edi ecx eax + ret + +save_hd_wait_timeout: + + push eax + mov eax,[timer_ticks];[0xfdf0] + add eax,300 ; 3 sec timeout + mov [hd_wait_timeout],eax + pop eax + ret + +align 4 +check_hd_wait_timeout: + + push eax + mov eax,[hd_wait_timeout] + cmp [timer_ticks], eax ;[0xfdf0],eax + jg hd_timeout_error + pop eax + mov [hd_error],0 + ret + +iglobal + hd_timeout_str db 'K : FS - HD timeout',13,10,0 + hd_read_str db 'K : FS - HD read error',13,10,0 + hd_write_str db 'K : FS - HD write error',13,10,0 + hd_lba_str db 'K : FS - HD LBA error',13,10,0 +endg + +hd_timeout_error: + + call clear_hd_cache + call clear_application_table_status + mov esi,hd_timeout_str + call sys_msg_board_str +; jmp $ + mov [hd_error],1 + pop eax + ret + +hd_read_error: + + call clear_hd_cache + call clear_application_table_status + mov esi,hd_read_str + call sys_msg_board_str + pop edx eax + jmp return_01 +; jmp $ + +hd_write_error: + + call clear_hd_cache + call clear_application_table_status + mov esi,hd_write_str + call sys_msg_board_str + jmp return_02 +; jmp $ + +hd_write_error_dma: + call clear_hd_cache + call clear_application_table_status + mov esi, hd_write_str + call sys_msg_board_str + pop esi + jmp return_02 + +hd_lba_error: + call clear_hd_cache + call clear_application_table_status + mov esi,hd_lba_str + call sys_msg_board_str + jmp LBA_read_ret + + +align 4 +wait_for_hd_idle: + + push eax edx + + call save_hd_wait_timeout + + mov edx,[hdbase] + add edx,0x7 + + wfhil1: + + call check_hd_wait_timeout + cmp [hd_error],0 + jne @f + + in al,dx + test al,128 + jnz wfhil1 + + @@: + + pop edx eax + ret + + +align 4 +wait_for_sector_buffer: + + push eax edx + + mov edx,[hdbase] + add edx,0x7 + + call save_hd_wait_timeout + + hdwait_sbuf: ; wait for sector buffer to be ready + + call check_hd_wait_timeout + cmp [hd_error],0 + jne @f + + in al,dx + test al,8 + jz hdwait_sbuf + + mov [hd_error],0 + + cmp [hd_setup],1 ; do not mark error for setup request + je buf_wait_ok + + test al,1 ; previous command ended up with an error + jz buf_wait_ok + @@: + mov [hd_error],1 + + buf_wait_ok: + + pop edx eax + ret + +align 4 +wait_for_sector_dma_ide0: + push eax + push edx + call save_hd_wait_timeout +.wait: + call change_task + cmp [irq14_func], hdd_irq14 + jnz .done + call check_hd_wait_timeout + cmp [hd_error], 0 + jz .wait + mov [irq14_func], hdd_irq_null + mov dx, [IDEContrRegsBaseAddr] + mov al, 0 + out dx, al +.done: + pop edx + pop eax + ret + +align 4 +wait_for_sector_dma_ide1: + push eax + push edx + call save_hd_wait_timeout +.wait: + call change_task + cmp [irq15_func], hdd_irq15 + jnz .done + call check_hd_wait_timeout + cmp [hd_error], 0 + jz .wait + mov [irq15_func], hdd_irq_null + mov dx, [IDEContrRegsBaseAddr] + add dx, 8 + mov al, 0 + out dx, al +.done: + pop edx + pop eax + ret + +iglobal +align 4 +; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary +IDE_descriptor_table: + dd 284000h + dw 2000h + dw 8000h + +dma_cur_sector dd not 40h +irq14_func dd hdd_irq_null +irq15_func dd hdd_irq_null +endg + +uglobal +; all uglobals are zeroed at boot +dma_process dd 0 +dma_slot_ptr dd 0 +cache_chain_pos dd 0 +cache_chain_ptr dd 0 +cache_chain_size db 0 +cache_chain_started db 0 +dma_task_switched db 0 +dma_hdd db 0 +endg + +align 4 +hdd_irq14: + pushfd + cli + pushad + mov [irq14_func], hdd_irq_null + mov dx, [IDEContrRegsBaseAddr] + mov al, 0 + out dx, al + call update_counters + mov ebx, [dma_process] + cmp [0x3000], ebx + jz .noswitch + mov [dma_task_switched], 1 + mov edi, [dma_slot_ptr] + mov eax, [0x3000] + mov [dma_process], eax + mov eax, [0x3010] + mov [dma_slot_ptr], eax + mov [0x3000], ebx + mov [0x3010], edi + mov byte [0xFFFF], 1 + call do_change_task +.noswitch: + popad + popfd +align 4 +hdd_irq_null: + ret + +align 4 +hdd_irq15: + pushfd + cli + pushad + mov [irq15_func], hdd_irq_null + mov dx, [IDEContrRegsBaseAddr] + add dx, 8 + mov al, 0 + out dx, al + call update_counters + mov ebx, [dma_process] + cmp [0x3000], ebx + jz .noswitch + mov [dma_task_switched], 1 + mov edi, [dma_slot_ptr] + mov eax, [0x3000] + mov [dma_process], eax + mov eax, [0x3010] + mov [dma_slot_ptr], eax + mov [0x3000], ebx + mov [0x3010], edi + mov byte [0xFFFF], 1 + call do_change_task +.noswitch: + popad + popfd + ret + +align 4 +hd_read_dma: + push eax + push edx + mov edx, [dma_cur_sector] + cmp eax, edx + jb .notread + add edx, 15 + cmp [esp+4], edx + ja .notread + mov eax, [esp+4] + sub eax, [dma_cur_sector] + shl eax, 9 + add eax, 0x284000 + push ecx esi edi + mov esi, eax + shl edi, 9 + add edi, 0x610000 + mov ecx, 512/4 + cld + rep movsd + pop edi esi ecx + pop edx + pop eax + ret +.notread: + mov eax, IDE_descriptor_table + mov dword [eax], 0x284000 + mov word [eax+4], 0x2000 + mov dx, [IDEContrRegsBaseAddr] + cmp [hdbase], 0x1F0 + jz @f + add edx, 8 +@@: + push edx + add edx, 4 + out dx, eax + pop edx + mov al, 0 + out dx, al + add edx, 2 + mov al, 6 + out dx, al + call wait_for_hd_idle + cmp [hd_error], 0 + jnz hd_read_error + call disable_ide_int + xor eax, eax + mov edx, [hdbase] + inc edx + out dx, al + inc edx + mov eax, 10h + out dx, al + inc edx + mov eax, [esp+4] + out dx, al + shr eax, 8 + inc edx + out dx, al + shr eax, 8 + inc edx + out dx, al + shr eax, 8 + inc edx + and al, 0xF + add al, byte [hdid] + add al, 11100000b + out dx, al + inc edx + mov al, 0xC8 + out dx, al + mov dx, [IDEContrRegsBaseAddr] + cmp [hdbase], 0x1F0 + jz @f + add dx, 8 +@@: + mov al, 9 + out dx, al + mov eax, [0x3000] + mov [dma_process], eax + mov eax, [0x3010] + mov [dma_slot_ptr], eax + cmp [hdbase], 0x1F0 + jnz .ide1 + mov [irq14_func], hdd_irq14 + jmp @f +.ide1: + mov [irq15_func], hdd_irq15 +@@: + call enable_ide_int + cmp [hdbase], 0x1F0 + jnz .wait_ide1 + call wait_for_sector_dma_ide0 + jmp @f +.wait_ide1: + call wait_for_sector_dma_ide1 +@@: + cmp [hd_error], 0 + jnz hd_read_error + pop edx + pop eax + mov [dma_cur_sector], eax + jmp hd_read_dma + +align 4 +write_cache_chain: + push esi + mov eax, IDE_descriptor_table + mov edx, [cache_chain_pos] + shl edx, 9 + add edx, 0x610000 + mov [eax], edx + movzx edx, [cache_chain_size] + shl edx, 9 + mov [eax+4], dx + jmp do_write_dma +write_cache_sector: + push esi + mov eax, IDE_descriptor_table + mov edx, edi + shl edx, 9 + add edx, 0x610000 + mov [eax], edx + mov word [eax+4], 0x200 +do_write_dma: + mov dx, [IDEContrRegsBaseAddr] + cmp [hdbase], 0x1F0 + jz @f + add edx, 8 +@@: + push edx + add edx, 4 + out dx, eax + pop edx + mov al, 0 + out dx, al + add edx, 2 + mov al, 6 + out dx, al + call wait_for_hd_idle + cmp [hd_error], 0 + jnz hd_write_error_dma + call disable_ide_int + xor eax, eax + mov edx, [hdbase] + inc edx + out dx, al + inc edx + mov al, [cache_chain_size] + out dx, al + inc edx + mov esi, [cache_chain_ptr] + mov eax, [esi] + out dx, al + shr eax, 8 + inc edx + out dx, al + shr eax, 8 + inc edx + out dx, al + shr eax, 8 + inc edx + and al, 0xF + add al, byte [hdid] + add al, 11100000b + out dx, al + inc edx + mov al, 0xCA + out dx, al + mov dx, [IDEContrRegsBaseAddr] + cmp [hdbase], 0x1F0 + jz @f + add dx, 8 +@@: + mov al, 1 + out dx, al + mov eax, [0x3000] + mov [dma_process], eax + mov eax, [0x3010] + mov [dma_slot_ptr], eax + cmp [hdbase], 0x1F0 + jnz .ide1 + mov [irq14_func], hdd_irq14 + jmp @f +.ide1: + mov [irq15_func], hdd_irq15 +@@: + call enable_ide_int + mov [dma_cur_sector], not 0x40 + cmp [hdbase], 0x1F0 + jnz .wait_ide1 + call wait_for_sector_dma_ide0 + jmp @f +.wait_ide1: + call wait_for_sector_dma_ide1 +@@: + cmp [hd_error], 0 + jnz hd_write_error_dma + pop esi + ret + +uglobal +IDEContrRegsBaseAddr dw ? +endg diff --git a/kernel/trunk/boot/bootcode.inc b/kernel/trunk/boot/bootcode.inc index 5321288ce5..2b1c76f951 100644 --- a/kernel/trunk/boot/bootcode.inc +++ b/kernel/trunk/boot/bootcode.inc @@ -361,6 +361,46 @@ sayerr: ; test al,2 ;яЁютхЁър сшЄр уюЄютэюёЄш ; loopnz test_kbd + push 0 + pop es + and word [es:0x9031], 0 +; check for PCI BIOS + mov ax, 0xB101 + int 0x1A + jc .nopci + cmp edx, 'PCI ' + jnz .nopci +; find PCI class code +; class 1 = mass storage +; subclass 1 = IDE controller +; a) class 1, subclass 1, programming interface 0x80 + mov ax, 0xB103 + mov ecx, 1*10000h + 1*100h + 0x80 + mov si, 0 ; device index = 0 + int 0x1A + jnc .found +; b) class 1, subclass 1, programming interface 0x85 + mov ax, 0xB103 + mov ecx, 1*10000h + 1*100h + 0x85 + mov si, 0 ; device index = 0 + int 0x1A + jnc .found +; c) class 1, subclass 1, programming interface 0x8A + mov ax, 0xB103 + mov ecx, 1*10000h + 1*100h + 0x8A + mov si, 0 + int 0x1A + jc .nopci +.found: +; get memory base + mov ax, 0xB10A + mov di, 0x20 ; memory base is config register at 0x20 + int 0x1A + jc .nopci + and cx, 0xFFF0 ; clear address decode type + mov [es:0x9031], cx +.nopci: + mov al,0xf6 ; ╤сЁюё ъыртшрЄєЁ√, ЁрчЁх°шЄ№ ёърэшЁютрэшх out 0x60,al xor cx,cx diff --git a/kernel/trunk/core/sys32.inc b/kernel/trunk/core/sys32.inc index d87656732f..68958d3975 100644 --- a/kernel/trunk/core/sys32.inc +++ b/kernel/trunk/core/sys32.inc @@ -380,7 +380,7 @@ macro irqh [num] jmp irq_c } -irqh 2,5,7,8,9,10,11,14,15 +irqh 2,5,7,8,9,10,11 irq_c: mov ax, os_data @@ -441,6 +441,25 @@ p_irq12: restore_ring3_context iret +p_irq14: + save_ring3_context + mov ax, os_data + mov ds, ax + mov es, ax + call [irq14_func] + call ready_for_next_irq_1 + restore_ring3_context + iret +p_irq15: + save_ring3_context + mov ax, os_data + mov ds, ax + mov es, ax + call [irq15_func] + call ready_for_next_irq_1 + restore_ring3_context + iret + ready_for_next_irq: mov [check_idle_semaphore],5 mov al, 0x20 @@ -863,8 +882,8 @@ terminate: ; terminate application add edi, window_data ; \begin{diamond}[19.09.2006] ; skip minimized windows - test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED - jnz .check_next_window + test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED + jnz .check_next_window ; \end{diamond} call waredraw .nothing_to_activate: diff --git a/kernel/trunk/fs/fat32.inc b/kernel/trunk/fs/fat32.inc index 824e4109b6..fbea699844 100644 --- a/kernel/trunk/fs/fat32.inc +++ b/kernel/trunk/fs/fat32.inc @@ -166,20 +166,6 @@ free_hd_channel: mov [IDE_Channel_2],0 ret ;******************************************** -clear_hd_cache: - - push eax ecx edi - mov edi,0x600000 - mov ecx,16384 - xor eax,eax - cld - rep stosd ; clear hd cache with 0 - mov [cache_search_start],eax - mov [fat_in_cache],-1 - mov [fat_change],0 - pop edi ecx eax - ret - problem_partition db 0 ; used for partitions search include 'part_set.inc' @@ -1926,451 +1912,6 @@ update_disk: update_disk_acces_denied: ret - -;************************************************************************** -; -; 0x600008 - first entry in cache list -; -; +0 - lba sector -; +4 - state of cache sector -; 0 = empty -; 1 = used for read ( same as in hd ) -; 2 = used for write ( differs from hd ) -; -; +65536 - cache entries -; -;************************************************************************** - - -hd_read: -;----------------------------------------------------------- -; input : eax = block to read -; ebx = destination -;----------------------------------------------------------- - push ecx esi edi ; scan cache - - mov ecx,cache_max ; entries in cache - mov esi,0x600000+8 - mov edi,1 - - hdreadcache: - - cmp dword [esi+4],0 ; empty - je nohdcache - - cmp [esi],eax ; correct sector - je yeshdcache - - nohdcache: - - add esi,8 - inc edi - dec ecx - jnz hdreadcache - - call find_empty_slot ; ret in edi - cmp [hd_error],0 - jne return_01 - - push eax edx - - call disable_ide_int - - call wait_for_hd_idle - cmp [hd_error],0 - jne hd_read_error - -; cli - xor eax,eax - mov edx,[hdbase] - inc edx - out dx,al ; ATAFeatures регистр "особенностей" - inc edx - inc eax - out dx,al ; ATASectorCount счетчик секторов - inc edx - mov eax,[esp+4] - out dx,al ; ATASectorNumber регистр номера сектора - shr eax,8 - inc edx - out dx,al ; ATACylinder номер цилиндра (младший байт) - shr eax,8 - inc edx - out dx,al ; номер цилиндра (старший байт) - shr eax,8 - inc edx - and al,1+2+4+8 - add al,byte [hdid] - add al,128+64+32 - out dx,al ; номер головки/номер диска - inc edx - mov al,20h - out dx,al ; ATACommand регистр команд -; sti - - call wait_for_sector_buffer - - cmp [hd_error],0 - jne hd_read_error - -; cli - push edi - shl edi,9 - add edi,0x600000+65536 - mov ecx,256 - mov edx,[hdbase] - cld - rep insw - pop edi -; sti - - call enable_ide_int - - pop edx eax - blok_read_2: - lea esi,[edi*8+0x600000] - mov [esi],eax ; sector number - mov dword [esi+4],1 ; hd read - mark as same as in hd - - yeshdcache: - - mov esi,edi - shl esi,9 - add esi,0x600000+65536 - mov edi,ebx - mov ecx,512/4 - cld - rep movsd ; move data - return_01: - pop edi esi ecx - ret - -disable_ide_int: - mov edx,[hdbase] - add edx,0x206 - mov al,2 - out dx,al - ret - -enable_ide_int: - mov edx,[hdbase] - add edx,0x206 - mov al,0 - out dx,al - ret - -hd_write: -;----------------------------------------------------------- -; input : eax = block -; ebx = pointer to memory -;----------------------------------------------------------- - push ecx esi edi - - ; check if the cache already has the sector and overwrite it - - mov ecx,cache_max - mov esi,0x600000+8 - mov edi,1 - - hdwritecache: - - cmp dword [esi+4],0 ; if cache slot is empty - je not_in_cache_write - - cmp [esi],eax ; if the slot has the sector - je yes_in_cache_write - - not_in_cache_write: - - add esi,8 - inc edi - dec ecx - jnz hdwritecache - - ; sector not found in cache - ; write the block to a new location - - call find_empty_slot ; ret in edi - cmp [hd_error],0 - jne hd_write_access_denied - - lea esi,[edi*8+0x600000] - mov [esi],eax ; sector number - - yes_in_cache_write: - - mov dword [esi+4],2 ; write - differs from hd - - shl edi,9 - add edi,0x600000+65536 - mov esi,ebx - mov ecx,512/4 - cld - rep movsd ; move data - hd_write_access_denied: - pop edi esi ecx - ret - - -write_cache: -;----------------------------------------------------------- -; write all changed sectors to disk -;----------------------------------------------------------- - push eax ecx edx esi edi - - ; write difference ( 2 ) from cache to hd - - mov ecx,cache_max - mov esi,0x600000+8 - mov edi,1 - - write_cache_more: - - cmp dword [esi+4],2 ; if cache slot is not different - jne does_not_need_writing - - mov dword [esi+4],1 ; same as in hd - mov eax,[esi] ; eax = sector to write - - cmp eax,[PARTITION_START] - jb danger - cmp eax,[PARTITION_END] - ja danger - - call disable_ide_int - - call wait_for_hd_idle - cmp [hd_error],0 - jne hd_write_error - -; cli - xor eax,eax - mov edx,[hdbase] - inc edx - out dx,al - inc edx - inc eax - out dx,al - inc edx - mov eax,[esi] ; eax = sector to write - out dx,al - shr eax,8 - inc edx - out dx,al - shr eax,8 - inc edx - out dx,al - shr eax,8 - inc edx - and al,1+2+4+8 - add al,byte [hdid] - add al,128+64+32 - out dx,al - inc edx - mov al,30h - out dx,al -; sti - - call wait_for_sector_buffer - - cmp [hd_error],0 - jne hd_write_error - - push ecx esi - -; cli - mov esi,edi - shl esi,9 - add esi,0x600000+65536 ; esi = from memory position - mov ecx,256 - mov edx,[hdbase] - cld - rep outsw -; sti - - pop esi ecx - - call enable_ide_int - - danger: - does_not_need_writing: - - add esi,8 - inc edi - dec ecx - jnz write_cache_more - return_02: - pop edi esi edx ecx eax - ret - - -find_empty_slot: -;----------------------------------------------------------- -; find empty or read slot, flush cache if next 10% is used by write -; output : edi = cache slot -;----------------------------------------------------------- - push ecx esi - - search_again: - - mov ecx,cache_max*10/100 - mov edi,[cache_search_start] - - search_for_empty: - - inc edi - cmp edi,cache_max - jbe inside_cache - mov edi,1 - - inside_cache: - - cmp dword [edi*8+0x600000+4],2 ; get cache slot info - jb found_slot ; it's empty or read - dec ecx - jnz search_for_empty - - call write_cache ; no empty slots found, write all - cmp [hd_error],0 - jne found_slot_access_denied - - jmp search_again ; and start again - - found_slot: - - mov [cache_search_start],edi - found_slot_access_denied: - pop esi ecx - ret - - -save_hd_wait_timeout: - - push eax - mov eax,[timer_ticks];[0xfdf0] - add eax,300 ; 3 sec timeout - mov [hd_wait_timeout],eax - pop eax - ret - - -check_hd_wait_timeout: - - push eax - mov eax,[hd_wait_timeout] - cmp [timer_ticks], eax ;[0xfdf0],eax - jg hd_timeout_error - pop eax - mov [hd_error],0 - ret - -iglobal - hd_timeout_str db 'K : FS - HD timeout',13,10,0 - hd_read_str db 'K : FS - HD read error',13,10,0 - hd_write_str db 'K : FS - HD write error',13,10,0 - hd_lba_str db 'K : FS - HD LBA error',13,10,0 -endg - -hd_timeout_error: - - call clear_hd_cache - call clear_application_table_status - mov esi,hd_timeout_str - call sys_msg_board_str -; jmp $ - mov [hd_error],1 - pop eax - ret - -hd_read_error: - - call clear_hd_cache - call clear_application_table_status - mov esi,hd_read_str - call sys_msg_board_str - pop edx eax - jmp return_01 -; jmp $ - -hd_write_error: - - call clear_hd_cache - call clear_application_table_status - mov esi,hd_write_str - call sys_msg_board_str - jmp return_02 -; jmp $ - -hd_lba_error: - call clear_hd_cache - call clear_application_table_status - mov esi,hd_lba_str - call sys_msg_board_str - jmp LBA_read_ret - - -wait_for_hd_idle: - - push eax edx - - call save_hd_wait_timeout - - mov edx,[hdbase] - add edx,0x7 - - wfhil1: - - call check_hd_wait_timeout - cmp [hd_error],0 - jne @f - - in al,dx - test al,128 - jnz wfhil1 - - @@: - - pop edx eax - ret - - - -wait_for_sector_buffer: - - push eax edx - - mov edx,[hdbase] - add edx,0x7 - - call save_hd_wait_timeout - - hdwait_sbuf: ; wait for sector buffer to be ready - - call check_hd_wait_timeout - cmp [hd_error],0 - jne @f - - in al,dx - test al,8 - jz hdwait_sbuf - - mov [hd_error],0 - - cmp [hd_setup],1 ; do not mark error for setup request - je buf_wait_ok - - test al,1 ; previous command ended up with an error - jz buf_wait_ok - @@: - mov [hd_error],1 - - buf_wait_ok: - - pop edx eax - ret - - - read_hd_file: ;----------------------------------------------------------------- ; diff --git a/kernel/trunk/kernel.asm b/kernel/trunk/kernel.asm index d32017f950..799845cca1 100644 --- a/kernel/trunk/kernel.asm +++ b/kernel/trunk/kernel.asm @@ -288,6 +288,8 @@ B32: rep stosd ; SAVE REAL MODE VARIABLES + mov ax, [0x2f0000 + 0x9031] + mov [IDEContrRegsBaseAddr], ax ; --------------- APM --------------------- mov eax, [0x2f0000 + 0x9040] ; entry point mov dword[apm_entry], eax @@ -817,6 +819,8 @@ finit ;reset the registers, contents which are still equal RM loop ready_for_irqs ; flush the queue ; mov [dma_hdd],1 + cmp [IDEContrRegsBaseAddr], 0 + setnz [dma_hdd] sti jmp $ ; wait here for timer to take control diff --git a/kernel/trunk/kernel32.inc b/kernel/trunk/kernel32.inc index 7eb691bf1a..ea1c6bdf67 100644 --- a/kernel/trunk/kernel32.inc +++ b/kernel/trunk/kernel32.inc @@ -239,6 +239,9 @@ include "bus/pci/pci32.inc" include "blkdev/fdc.inc" include "blkdev/flp_drv.inc" +; HD drive controller +include "blkdev/hd_drv.inc" + ; CD drive controller include "blkdev/cdrom.inc"