Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 3711 → Rev 3712

/kernel/trunk/blkdev/hd_drv.inc
11,7 → 11,8
; Low-level driver for HDD access
; DMA support by Mario79
; Access through BIOS by diamond
 
; LBA48 support by Mario79
;-----------------------------------------------------------------------------
align 4
hd_read:
;-----------------------------------------------------------
21,8 → 22,6
and [hd_error], 0
push ecx esi edi ; scan cache
 
; mov ecx,cache_max ; entries in cache
; mov esi,HD_CACHE+8
call calculate_cache
add esi, 8
 
29,7 → 28,6
mov edi, 1
 
hdreadcache:
 
cmp dword [esi+4], 0; empty
je nohdcache
 
37,7 → 35,6
je yeshdcache
 
nohdcache:
 
add esi, 8
inc edi
dec ecx
49,12 → 46,6
; Read through BIOS?
cmp [hdpos], 0x80
jae .bios
; hd_read_{dma,pio} use old ATA with 28 bit for sector number
; cmp eax, 0x10000000
; jb @f
; inc [hd_error]
; jmp return_01
;@@:
; DMA read is permitted if [allow_dma_access]=1 or 2
cmp [allow_dma_access], 2
ja .nodma
70,20 → 61,17
@@:
cmp [hd_error], 0
jne return_01
; lea esi,[edi*8+HD_CACHE]
; push eax
 
call calculate_cache_1
lea esi, [edi*8+esi]
; pop eax
 
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,HD_CACHE+65536
 
push eax
call calculate_cache_2
add esi, eax
93,15 → 81,16
mov ecx, 512/4
cld
rep movsd ; move data
 
return_01:
pop edi esi ecx
ret
 
;-----------------------------------------------------------------------------
align 4
hd_read_pio:
push eax edx
 
; Выбрать нужный диск
; Select the desired drive
mov edx, [hdbase]
add edx, 6 ;адрес регистра головок
mov al, byte [hdid]
116,6 → 105,7
mov eax, [esp+4]
cmp eax, 0x10000000
jae .lba48
;--------------------------------------
.lba28:
pushfd
cli
146,6 → 136,7
out dx, al ; ATACommand регистр команд
popfd
jmp .continue
;--------------------------------------
.lba48:
pushfd
cli
184,6 → 175,7
mov al, 24h ; READ SECTOR(S) EXT
out dx, al; ATACommand регистр команд
popfd
;--------------------------------------
.continue:
call wait_for_sector_buffer
 
190,10 → 182,11
cmp [hd_error], 0
jne hd_read_error
 
pushfd
cli
push edi
shl edi, 9
; add edi,HD_CACHE+65536
 
push eax
call calculate_cache_2
add edi, eax
204,27 → 197,11
cld
rep insw
pop edi
sti
popfd
 
pop edx eax
ret
 
disable_ide_int:
; mov edx,[hdbase]
; add edx,0x206
; mov al,2
; out dx,al
cli
ret
 
enable_ide_int:
; mov edx,[hdbase]
; add edx,0x206
; mov al,0
; out dx,al
sti
ret
 
;-----------------------------------------------------------------------------
align 4
hd_write:
;-----------------------------------------------------------
234,16 → 211,11
push ecx esi edi
 
; check if the cache already has the sector and overwrite it
 
; mov ecx,cache_max
; mov esi,HD_CACHE+8
call calculate_cache
add esi, 8
 
mov edi, 1
 
hdwritecache:
 
cmp dword [esi+4], 0; if cache slot is empty
je not_in_cache_write
 
251,7 → 223,6
je yes_in_cache_write
 
not_in_cache_write:
 
add esi, 8
inc edi
dec ecx
259,25 → 230,19
 
; 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+HD_CACHE]
; push eax
call calculate_cache_1
lea esi, [edi*8+esi]
; pop eax
 
mov [esi], eax ; sector number
 
yes_in_cache_write:
 
mov dword [esi+4], 2; write - differs from hd
 
shl edi, 9
; add edi,HD_CACHE+65536
 
push eax
call calculate_cache_2
add edi, eax
287,15 → 252,14
mov ecx, 512/4
cld
rep movsd ; move data
 
hd_write_access_denied:
pop edi esi ecx
ret
 
;-----------------------------------------------------------------------------
align 4
cache_write_pio:
; call disable_ide_int
 
; Выбрать нужный диск
; Select the desired drive
mov edx, [hdbase]
add edx, 6 ;адрес регистра головок
mov al, byte [hdid]
310,6 → 274,7
mov eax, [esi]
cmp eax, 0x10000000
jae .lba48
;--------------------------------------
.lba28:
pushfd
cli
340,6 → 305,7
out dx, al ; ATACommand регистр команд
popfd
jmp .continue
;--------------------------------------
.lba48:
pushfd
cli
378,6 → 344,7
mov al, 34h ; WRITE SECTOR(S) EXT
out dx, al; ATACommand регистр команд
popfd
;--------------------------------------
.continue:
call wait_for_sector_buffer
 
386,10 → 353,11
 
push ecx esi
 
pushfd
cli
mov esi, edi
shl esi, 9
; add esi,HD_CACHE+65536 ; esi = from memory position
 
push eax
call calculate_cache_2
add esi, eax
399,15 → 367,13
mov edx, [hdbase]
cld
rep outsw
sti
popfd
 
; call enable_ide_int
pop esi ecx
 
ret
 
;-----------------------------------------------------------------------------
align 4
save_hd_wait_timeout:
 
push eax
mov eax, [timer_ticks]
add eax, 300 ; 3 sec timeout
414,47 → 380,29
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
jg hd_timeout_error
 
pop eax
mov [hd_error], 0
ret
 
;iglobal
; hd_timeout_str db 'K : FS - HD timeout',0
; hd_read_str db 'K : FS - HD read error',0
; hd_write_str db 'K : FS - HD write error',0
; hd_lba_str db 'K : FS - HD LBA error',0
;endg
 
;-----------------------------------------------------------------------------
hd_timeout_error:
 
; call clear_hd_cache
; call clear_application_table_status
; mov esi,hd_timeout_str
; call sys_msg_board_str
if lang eq sp
DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
else
DEBUGF 1,"K : FS - HD timeout\n"
end if
 
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
if lang eq sp
DEBUGF 1,"K : FS - HD error de lectura\n"
else
462,13 → 410,10
end if
pop edx eax
ret
 
;-----------------------------------------------------------------------------
hd_write_error_dma:
pop esi
hd_write_error:
 
; call clear_hd_cache
; call clear_application_table_status
; mov esi,hd_write_str
; call sys_msg_board_str
if lang eq sp
DEBUGF 1,"K : FS - HD error de escritura\n"
else
475,25 → 420,8
DEBUGF 1,"K : FS - HD write error\n"
end if
ret
 
hd_write_error_dma:
; call clear_hd_cache
; call clear_application_table_status
; mov esi, hd_write_str
; call sys_msg_board_str
if lang eq sp
DEBUGF 1,"K : FS - HD error de escritura\n"
else
DEBUGF 1,"K : FS - HD write error\n"
end if
pop esi
ret
 
;-----------------------------------------------------------------------------
hd_lba_error:
; call clear_hd_cache
; call clear_application_table_status
; mov esi,hd_lba_str
; call sys_msg_board_str
if lang eq sp
DEBUGF 1,"K : FS - HD error en LBA\n"
else
500,11 → 428,9
DEBUGF 1,"K : FS - HD LBA error\n"
end if
jmp LBA_read_ret
 
 
;-----------------------------------------------------------------------------
align 4
wait_for_hd_idle:
 
push eax edx
 
call save_hd_wait_timeout
511,9 → 437,9
 
mov edx, [hdbase]
add edx, 0x7
 
;--------------------------------------
align 4
wfhil1:
 
call check_hd_wait_timeout
cmp [hd_error], 0
jne @f
523,14 → 449,11
jnz wfhil1
 
@@:
 
pop edx eax
ret
 
 
;-----------------------------------------------------------------------------
align 4
wait_for_sector_buffer:
 
push eax edx
 
mov edx, [hdbase]
537,9 → 460,9
add edx, 0x7
 
call save_hd_wait_timeout
 
;--------------------------------------
align 4
hdwait_sbuf: ; wait for sector buffer to be ready
 
call check_hd_wait_timeout
cmp [hd_error], 0
jne @f
559,16 → 482,16
mov [hd_error], 1
 
buf_wait_ok:
 
pop edx eax
ret
 
; \begin{Mario79}
;-----------------------------------------------------------------------------
align 4
wait_for_sector_dma_ide0:
push eax
push edx
call save_hd_wait_timeout
;--------------------------------------
align 4
.wait:
call change_task
cmp [irq14_func], hdd_irq14
584,12 → 507,14
pop edx
pop eax
ret
 
;-----------------------------------------------------------------------------
align 4
wait_for_sector_dma_ide1:
push eax
push edx
call save_hd_wait_timeout
;--------------------------------------
align 4
.wait:
call change_task
cmp [irq15_func], hdd_irq15
606,7 → 531,7
pop edx
pop eax
ret
 
;-----------------------------------------------------------------------------
iglobal
align 4
; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
620,7 → 545,7
irq14_func dd hdd_irq_null
irq15_func dd hdd_irq_null
endg
 
;-----------------------------------------------------------------------------
uglobal
; all uglobals are zeroed at boot
dma_process dd 0
633,7 → 558,7
dma_hdd db 0
allow_dma_access db 0
endg
 
;-----------------------------------------------------------------------------
align 4
hdd_irq14:
pushfd
643,27 → 568,12
mov dx, [IDEContrRegsBaseAddr]
mov al, 0
out dx, al
; call update_counters
; mov ebx, [dma_process]
; cmp [CURRENT_TASK], ebx
; jz .noswitch
; mov [dma_task_switched], 1
; mov edi, [dma_slot_ptr]
; mov eax, [CURRENT_TASK]
; mov [dma_process], eax
; mov eax, [TASK_BASE]
; mov [dma_slot_ptr], eax
; mov [CURRENT_TASK], ebx
; mov [TASK_BASE], edi
; mov byte [DONT_SWITCH], 1
; call do_change_task
.noswitch:
popad
popfd
align 4
hdd_irq_null:
ret
 
;-----------------------------------------------------------------------------
align 4
hdd_irq15:
pushfd
674,33 → 584,12
add dx, 8
mov al, 0
out dx, al
; call update_counters
; mov ebx, [dma_process]
; cmp [CURRENT_TASK], ebx
; jz .noswitch
; mov [dma_task_switched], 1
; mov edi, [dma_slot_ptr]
; mov eax, [CURRENT_TASK]
; mov [dma_process], eax
; mov eax, [TASK_BASE]
; mov [dma_slot_ptr], eax
; mov [CURRENT_TASK], ebx
; mov [TASK_BASE], edi
; mov byte [DONT_SWITCH], 1
; call do_change_task
.noswitch:
popad
popfd
ret
 
;-----------------------------------------------------------------------------
align 4
hd_read_dma:
; hd_read_dma use old ATA with 28 bit for sector number
cmp eax, 0x10000000
jb @f
inc [hd_error]
ret
@@:
push eax
push edx
mov edx, [dma_hdpos]
719,7 → 608,7
push ecx esi edi
mov esi, eax
shl edi, 9
; add edi, HD_CACHE+0x10000
 
push eax
call calculate_cache_2
add edi, eax
751,37 → 640,97
add edx, 2
mov al, 6
out dx, al
 
; Select the desired drive
mov edx, [hdbase]
add edx, 6 ; адрес регистра головок
mov al, byte [hdid]
add al, 128+64+32
out dx, al ; номер головки/номер диска
 
call wait_for_hd_idle
cmp [hd_error], 0
jnz hd_read_error
call disable_ide_int
 
; ATA with 28 or 48 bit for sector number?
mov eax, [esp+4]
; -10h because the PreCache hits the boundary between lba28 and lba48
; 10h = 16 - size of PreCache
cmp eax, 0x10000000-10h
jae .lba48
;--------------------------------------
.lba28:
pushfd
cli
xor eax, eax
mov edx, [hdbase]
inc edx
out dx, al
out dx, al ; ATA Features регистр "особенностей"
inc edx
mov eax, 10h
out dx, al
mov eax, 10h ; Sector Counter = 16 ; PreCache
out dx, al ; ATA Sector Counter счётчик секторов
inc edx
mov eax, [esp+4]
out dx, al
mov eax, [esp+4+4]
out dx, al ; LBA Low LBA (7:0)
shr eax, 8
inc edx
out dx, al
out dx, al ; LBA Mid LBA (15:8)
shr eax, 8
inc edx
out dx, al
out dx, al ; LBA High LBA (23:16)
shr eax, 8
inc edx
and al, 0xF
and al, 0xF ; LBA (27:24)
add al, byte [hdid]
add al, 11100000b
out dx, al
out dx, al ; номер головки/номер диска
inc edx
mov al, 0xC8
out dx, al
mov al, 0xC8 ; READ DMA
out dx, al ; ATACommand регистр команд
jmp .continue
;--------------------------------------
.lba48:
pushfd
cli
xor eax, eax
mov edx, [hdbase]
inc edx
out dx, al ; Features Previous Reserved
out dx, al ; Features Current Reserved
inc edx
out dx, al ; Sector Count Previous Sector count (15:8)
mov eax, 10h ; Sector Counter = 16 PreCache
out dx, al ; Sector Count Current Sector count (7:0)
inc edx
mov eax, [esp+4+4]
rol eax, 8
out dx, al ; LBA Low Previous LBA (31:24)
xor eax, eax ; because only 32 bit cache
inc edx
out dx, al ; LBA Mid Previous LBA (39:32)
inc edx
out dx, al ; LBA High Previous LBA (47:40)
sub edx, 2
mov eax, [esp+4+4]
out dx, al ; LBA Low Current LBA (7:0)
shr eax, 8
inc edx
out dx, al ; LBA Mid Current LBA (15:8)
shr eax, 8
inc edx
out dx, al ; LBA High Current LBA (23:16)
inc edx
mov al, byte [hdid]
add al, 128+64+32
out dx, al ; номер головки/номер диска
inc edx
mov al, 25h ; READ DMA EXT
out dx, al ; ATACommand регистр команд
;--------------------------------------
.continue:
mov dx, [IDEContrRegsBaseAddr]
cmp [hdbase], 0x1F0
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
jz @f
add dx, 8
@@:
791,7 → 740,8
mov [dma_process], eax
mov eax, [TASK_BASE]
mov [dma_slot_ptr], eax
cmp [hdbase], 0x1F0
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
jnz .ide1
mov [irq14_func], hdd_irq14
jmp @f
798,8 → 748,9
.ide1:
mov [irq15_func], hdd_irq15
@@:
call enable_ide_int
cmp [hdbase], 0x1F0
popfd
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
jnz .wait_ide1
call wait_for_sector_dma_ide0
jmp @f
814,17 → 765,17
pop eax
mov [dma_cur_sector], eax
jmp hd_read_dma
 
;-----------------------------------------------------------------------------
align 4
write_cache_sector:
mov [cache_chain_size], 1
mov [cache_chain_pos], edi
;--------------------------------------
align 4
write_cache_chain:
cmp [hdpos], 0x80
jae bd_write_cache_chain
mov eax, [cache_chain_ptr]
cmp dword[eax], 0x10000000
jae .bad
push esi
mov eax, IDE_descriptor_table
mov edx, eax
857,38 → 808,98
add edx, 2
mov al, 6
out dx, al
 
; Select the desired drive
mov edx, [hdbase]
add edx, 6 ; адрес регистра головок
mov al, byte [hdid]
add al, 128+64+32
out dx, al ; номер головки/номер диска
 
call wait_for_hd_idle
cmp [hd_error], 0
jnz hd_write_error_dma
call disable_ide_int
 
; ATA with 28 or 48 bit for sector number?
mov esi, [cache_chain_ptr]
mov eax, [esi]
; -40h because the PreCache hits the boundary between lba28 and lba48
; 40h = 64 - the maximum number of sectors to be written for one command
cmp eax, 0x10000000-40h
jae .lba48
;--------------------------------------
.lba28:
pushfd
cli
xor eax, eax
mov edx, [hdbase]
inc edx
out dx, al
out dx, al ; ATA Features регистр "особенностей"
inc edx
mov al, [cache_chain_size]
out dx, al
mov al, [cache_chain_size] ; Sector Counter
out dx, al ; ATA Sector Counter счётчик секторов
inc edx
mov esi, [cache_chain_ptr]
mov eax, [esi]
out dx, al
out dx, al ; LBA Low LBA (7:0)
shr eax, 8
inc edx
out dx, al
out dx, al ; LBA Mid LBA (15:8)
shr eax, 8
inc edx
out dx, al
out dx, al ; LBA High LBA (23:16)
shr eax, 8
inc edx
and al, 0xF
and al, 0xF ; LBA (27:24)
add al, byte [hdid]
add al, 11100000b
out dx, al
out dx, al ; номер головки/номер диска
inc edx
mov al, 0xCA
out dx, al
mov al, 0xCA ; WRITE DMA
out dx, al ; ATACommand регистр команд
jmp .continue
;--------------------------------------
.lba48:
pushfd
cli
xor eax, eax
mov edx, [hdbase]
inc edx
out dx, al ; Features Previous Reserved
out dx, al ; Features Current Reserved
inc edx
out dx, al ; Sector Count Previous Sector count (15:8)
mov al, [cache_chain_size] ; Sector Counter
out dx, al ; Sector Count Current Sector count (7:0)
inc edx
mov eax, [esi]
rol eax, 8
out dx, al ; LBA Low Previous LBA (31:24)
xor eax, eax ; because only 32 bit cache
inc edx
out dx, al ; LBA Mid Previous LBA (39:32)
inc edx
out dx, al ; LBA High Previous LBA (47:40)
sub edx, 2
mov eax, [esi]
out dx, al ; LBA Low Current LBA (7:0)
shr eax, 8
inc edx
out dx, al ; LBA Mid Current LBA (15:8)
shr eax, 8
inc edx
out dx, al ; LBA High Current LBA (23:16)
inc edx
mov al, byte [hdid]
add al, 128+64+32
out dx, al ; номер головки/номер диска
inc edx
mov al, 35h ; WRITE DMA EXT
out dx, al ; ATACommand регистр команд
;--------------------------------------
.continue:
mov dx, [IDEContrRegsBaseAddr]
cmp [hdbase], 0x1F0
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
jz @f
add dx, 8
@@:
898,7 → 909,8
mov [dma_process], eax
mov eax, [TASK_BASE]
mov [dma_slot_ptr], eax
cmp [hdbase], 0x1F0
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
jnz .ide1
mov [irq14_func], hdd_irq14
jmp @f
905,9 → 917,10
.ide1:
mov [irq15_func], hdd_irq15
@@:
call enable_ide_int
popfd
mov [dma_cur_sector], not 0x40
cmp [hdbase], 0x1F0
mov eax, [hd_address_table]
cmp [hdbase], eax ; 0x1F0
jnz .wait_ide1
call wait_for_sector_dma_ide0
jmp @f
918,10 → 931,7
jnz hd_write_error_dma
pop esi
ret
.bad:
inc [hd_error]
ret
 
;-----------------------------------------------------------------------------
uglobal
IDEContrRegsBaseAddr dw ?
IDEContrProgrammingInterface dw ?
930,8 → 940,7
IDE_BAR2_val dw ?
IDE_BAR3_val dw ?
endg
; \end{Mario79}
 
;-----------------------------------------------------------------------------
; \begin{diamond}
uglobal
bios_hdpos dd 0 ; 0 is invalid value for [hdpos]
938,6 → 947,8
bios_cur_sector dd ?
bios_read_len dd ?
endg
;-----------------------------------------------------------------------------
align 4
bd_read:
push eax
push edx
957,7 → 968,7
push ecx esi edi
mov esi, eax
shl edi, 9
; add edi, HD_CACHE+0x10000
 
push eax
call calculate_cache_2
add edi, eax
991,7 → 1002,8
.v86err:
mov [hd_error], 1
jmp hd_read_error
 
;-----------------------------------------------------------------------------
align 4
bd_write_cache_chain:
pusha
mov esi, [cache_chain_pos]
1019,12 → 1031,13
popa
mov [hd_error], 1
jmp hd_write_error
 
;-----------------------------------------------------------------------------
uglobal
int13_regs_in rb sizeof.v86_regs
int13_regs_out rb sizeof.v86_regs
endg
 
;-----------------------------------------------------------------------------
align 4
int13_call:
; Because this code uses fixed addresses,
; it can not be run simultaniously by many threads.
1075,9 → 1088,9
@@:
ret
; \end{diamond}
 
;-----------------------------------------------------------------------------
align 4
reserve_hd1:
 
cli
cmp [hd1_status], 0
je reserve_ok1
1087,7 → 1100,6
jmp reserve_hd1
 
reserve_ok1:
 
push eax
mov eax, [CURRENT_TASK]
shl eax, 5
1096,12 → 1108,12
pop eax
sti
ret
;********************************************
 
;-----------------------------------------------------------------------------
uglobal
hd_in_cache db ?
endg
 
;-----------------------------------------------------------------------------
align 4
reserve_hd_channel:
; BIOS disk accesses are protected with common mutex hd1_status
; This must be modified when hd1_status will not be valid!
1140,7 → 1152,7
sti
.ret:
ret
 
;-----------------------------------------------------------------------------
free_hd_channel:
; see comment at reserve_hd_channel
cmp [hdpos], 0x80
1154,4 → 1166,4
.IDE_Channel_2:
mov [IDE_Channel_2], 0
ret
;********************************************
;-----------------------------------------------------------------------------