Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 5568 → Rev 5569

/kernel/trunk/blkdev/hd_drv.inc
7,17 → 7,14
 
$Revision$
 
; HDD driver
 
; Low-level driver for HDD access
; DMA support by Mario79
; LBA48 support by Mario79
;-----------------------------------------------------------------------------
struct HD_DATA
hdbase dd ?
hdid dd ?
hdpos dd ?
ends
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------
iglobal
align 4
ide_callbacks:
52,7 → 49,7
dd ide_channel5_mutex
dd ide_channel6_mutex
endg
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------
uglobal
ide_mutex MUTEX
ide_channel1_mutex MUTEX
61,9 → 58,17
ide_channel4_mutex MUTEX
ide_channel5_mutex MUTEX
ide_channel6_mutex MUTEX
blockSize:
rb 4
sector:
rb 6
allow_dma_access db ?
IDE_common_irq_param db ?
eventPointer dd ?
eventID dd ?
endg
;-----------------------------------------------------------------------------
proc ide_read stdcall uses edi, \
;-----------------------------------------------------------------
proc ide_read stdcall uses esi edi ebx, \
hd_data, buffer, startsector:qword, numsectors
; hd_data = pointer to hd*_data
; buffer = pointer to buffer for data
74,16 → 79,14
sectors_todo dd ?
channel_lock dd ?
endl
; 1. Initialize number of sectors: get number of requested sectors
; and say that no sectors were read yet.
; get number of requested sectors and say that no sectors were read yet
mov ecx, [numsectors]
mov eax, [ecx]
mov dword [ecx], 0
mov [sectors_todo], eax
; 2. Acquire the global lock.
; acquire the global lock
mov ecx, ide_mutex
call mutex_lock
 
mov ecx, [hd_data]
mov ecx, [ecx+HD_DATA.hdpos]
dec ecx
92,13 → 95,7
mov ecx, [ecx + ide_mutex_table]
mov [channel_lock], ecx
call mutex_lock
; 3. Convert parameters to the form suitable for worker procedures.
; Underlying procedures do not know about 64-bit sectors.
; Worker procedures use global variables and edi for [buffer].
cmp dword [startsector+4], 0
jnz .fail
 
and [hd_error], 0
; prepare worker procedures variables
mov ecx, [hd_data]
mov eax, [ecx+HD_DATA.hdbase]
mov [hdbase], eax
107,14 → 104,11
mov eax, [ecx+HD_DATA.hdpos]
mov [hdpos], eax
mov eax, dword [startsector]
mov edi, [buffer]
; 4. Worker procedures take one sectors per time, so loop over all sectors to read.
.sectors_loop:
; DMA read is permitted if [allow_dma_access]=1 or 2
cmp [allow_dma_access], 2
ja .nodma
 
push eax ecx
mov [sector], eax
mov ax, word [startsector+4]
mov [sector+4], ax
mov esi, [buffer]
mov bl, 25h ; READ DMA EXT
mov ecx, [hdpos]
dec ecx
shr ecx, 2
121,7 → 115,6
imul ecx, sizeof.IDE_DATA
add ecx, IDE_controller_1
mov [IDE_controller_pointer], ecx
 
mov eax, [hdpos]
dec eax
and eax, 11b
128,51 → 121,43
shr eax, 1
add eax, ecx
cmp [eax+IDE_DATA.dma_hdd_channel_1], 1
pop ecx eax
jnz .nodma
 
call hd_read_dma
jmp @f
;--------------------------------------
.nodma:
call hd_read_pio
;--------------------------------------
jz .next
dec bl ; READ SECTOR(S) EXT
mov edi, esi
; worker procedures take max 8000h sectors per time
; loop until all sectors will be processed
.next:
mov ecx, 8000h
cmp ecx, [sectors_todo]
jbe @f
mov ecx, [sectors_todo]
@@:
cmp [hd_error], 0
jnz .fail
 
mov ecx, [numsectors]
inc dword [ecx] ; one more sector is read
dec [sectors_todo]
jz .done
 
inc eax
jnz .sectors_loop
;--------------------------------------
; 5. Loop is done, either due to error or because everything is done.
; Release the global lock and return the corresponding status.
.fail:
mov [blockSize], ecx
push ecx
call IDE_transfer
pop ecx
jc .out
mov eax, [numsectors]
add [eax], ecx
sub [sectors_todo], ecx
jz .out
add [sector], ecx
adc word [sector+4], 0
jmp .next
; loop is done, either due to error or because everything is done
; release the global lock and return the corresponding status
.out:
sbb eax, eax
push eax
mov ecx, [channel_lock]
call mutex_unlock
 
mov ecx, ide_mutex
call mutex_unlock
 
or eax, -1
pop eax
ret
;--------------------------------------
.done:
mov ecx, [channel_lock]
call mutex_unlock
 
mov ecx, ide_mutex
call mutex_unlock
 
xor eax, eax
ret
endp
;-----------------------------------------------------------------------------
proc ide_write stdcall uses esi edi, \
;-----------------------------------------------------------------
proc ide_write stdcall uses esi edi ebx, \
hd_data, buffer, startsector:qword, numsectors
; hd_data = pointer to hd*_data
; buffer = pointer to buffer with data
183,16 → 168,14
sectors_todo dd ?
channel_lock dd ?
endl
; 1. Initialize number of sectors: get number of requested sectors
; and say that no sectors were read yet.
; get number of requested sectors and say that no sectors were read yet
mov ecx, [numsectors]
mov eax, [ecx]
mov dword [ecx], 0
mov [sectors_todo], eax
; 2. Acquire the global lock.
; acquire the global lock
mov ecx, ide_mutex
call mutex_lock
 
mov ecx, [hd_data]
mov ecx, [ecx+HD_DATA.hdpos]
dec ecx
201,13 → 184,7
mov ecx, [ecx + ide_mutex_table]
mov [channel_lock], ecx
call mutex_lock
; 3. Convert parameters to the form suitable for worker procedures.
; Underlying procedures do not know about 64-bit sectors.
; Worker procedures use global variables and esi for [buffer].
cmp dword [startsector+4], 0
jnz .fail
 
and [hd_error], 0
; prepare worker procedures variables
mov ecx, [hd_data]
mov eax, [ecx+HD_DATA.hdbase]
mov [hdbase], eax
215,25 → 192,12
mov [hdid], eax
mov eax, [ecx+HD_DATA.hdpos]
mov [hdpos], eax
mov eax, dword [startsector]
mov [sector], eax
mov ax, word [startsector+4]
mov [sector+4], ax
mov esi, [buffer]
lea edi, [startsector]
mov [cache_chain_ptr], edi
; 4. Worker procedures take max 16 sectors per time,
; loop until all sectors will be processed.
.sectors_loop:
mov ecx, 16
cmp ecx, [sectors_todo]
jbe @f
 
mov ecx, [sectors_todo]
;--------------------------------------
@@:
mov [cache_chain_size], cl
; DMA write is permitted only if [allow_dma_access]=1
cmp [allow_dma_access], 2
jae .nodma
 
push eax ecx
mov bl, 35h ; WRITE DMA EXT
mov ecx, [hdpos]
dec ecx
shr ecx, 2
240,7 → 204,6
imul ecx, sizeof.IDE_DATA
add ecx, IDE_controller_1
mov [IDE_controller_pointer], ecx
 
mov eax, [hdpos]
dec eax
and eax, 11b
247,57 → 210,42
shr eax, 1
add eax, ecx
cmp [eax+IDE_DATA.dma_hdd_channel_1], 1
pop ecx eax
jnz .nodma
 
call cache_write_dma
jmp .common
;--------------------------------------
.nodma:
mov [cache_chain_size], 1
call cache_write_pio
;--------------------------------------
.common:
cmp [hd_error], 0
jnz .fail
 
movzx ecx, [cache_chain_size]
jz .next
dec bl ; WRITE SECTOR(S) EXT
; worker procedures take max 8000h sectors per time
; loop until all sectors will be processed
.next:
mov ecx, 8000h
cmp ecx, [sectors_todo]
jbe @f
mov ecx, [sectors_todo]
@@:
mov [blockSize], ecx
push ecx
call IDE_transfer
pop ecx
jc .out
mov eax, [numsectors]
add [eax], ecx
sub [sectors_todo], ecx
jz .done
 
add [edi], ecx
jc .fail
 
shl ecx, 9
add esi, ecx
jmp .sectors_loop
;--------------------------------------
; 5. Loop is done, either due to error or because everything is done.
; Release the global lock and return the corresponding status.
.fail:
jz .out
add [sector], ecx
adc word [sector+4], 0
jmp .next
; loop is done, either due to error or because everything is done
; release the global lock and return the corresponding status
.out:
sbb eax, eax
push eax
mov ecx, [channel_lock]
call mutex_unlock
 
mov ecx, ide_mutex
call mutex_unlock
 
or eax, -1
pop eax
ret
;--------------------------------------
.done:
mov ecx, [channel_lock]
call mutex_unlock
 
mov ecx, ide_mutex
call mutex_unlock
 
xor eax, eax
ret
endp
;-----------------------------------------------------------------------------
; This is a stub.
;-----------------------------------------------------------------
; this is a stub
proc ide_querymedia stdcall, hd_data, mediainfo
mov eax, [mediainfo]
mov [eax+DISKMEDIAINFO.Flags], 0
307,253 → 255,232
xor eax, eax
ret
endp
;-----------------------------------------------------------------------------
align 4
; input: eax = sector, edi -> buffer
; output: edi = edi + 512
hd_read_pio:
push eax edx
; Select the desired drive
;-----------------------------------------------------------------
; input: esi -> buffer, bl = command, [sector], [blockSize]
; output: esi -> next block in buffer
; for pio read esi equal edi
IDE_transfer:
mov edx, [hdbase]
add edx, 6 ;адрес регистра головок
add edx, 6
mov al, byte [hdid]
add al, 128+64+32
out dx, al; номер головки/номер диска
call wait_for_hd_idle
 
cmp [hd_error], 0
jne hd_read_error
; ATA with 28 or 48 bit for sector number?
mov eax, [esp+4]
cmp eax, 0x10000000
jae .lba48
;--------------------------------------
.lba28:
pushfd
add al, 224
out dx, al ; select the desired drive
call save_hd_wait_timeout
inc edx
@@:
call check_hd_wait_timeout
jc .hd_error
in al, dx
test al, 128 ; ready for command?
jnz @b
pushfd ; fill the ports
cli
xor eax, eax
mov edx, [hdbase]
inc edx
out dx, al ; ATA Features регистр "особенностей"
inc edx
inc eax
out dx, al ; ATA Sector Counter счётчик секторов
mov al, [blockSize+1]
out dx, al ; Sector count (15:8)
inc edx
mov eax, [esp+4+4]
out dx, al ; LBA Low LBA (7:0)
shr eax, 8
mov eax, [sector+3]
out dx, al ; LBA (31:24)
inc edx
out dx, al ; LBA Mid LBA (15:8)
shr eax, 8
out dx, al ; LBA (39:32)
inc edx
out dx, al ; LBA High LBA (23:16)
shr eax, 8
out dx, al ; LBA (47:40)
sub edx, 3
mov al, [blockSize]
out dx, al ; Sector count (7:0)
inc edx
and al, 1+2+4+8 ; LBA (27:24)
add al, byte [hdid]
add al, 128+64+32
out dx, al ; номер головки/номер диска
mov eax, [sector]
out dx, al ; LBA (7:0)
inc edx
mov al, 20h ; READ SECTOR(S)
out dx, al ; ATACommand регистр команд
popfd
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)
inc eax
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
out dx, al ; LBA (15:8)
inc edx
out dx, al ; LBA Mid Current LBA (15:8)
shr eax, 8
out dx, al ; LBA (23:16)
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, 24h ; READ SECTOR(S) EXT
out dx, al ; ATACommand регистр команд
popfd
;--------------------------------------
.continue:
call wait_for_sector_buffer
add al, 224
out dx, al
test bl, 1
jz .PIO
; DMA
mov dword [esp], 0x1000
call kernel_alloc
mov edi, eax
push eax
shl dword [blockSize], 9
mov eax, esi
add eax, [blockSize]
push eax
; check buffer pages physical addresses and fill the scatter-gather list
; buffer may be not aligned and may have size not divisible by page size
; [edi] = block physical address, [edi+4] = block size in bytes
; block addresses can not cross 10000h borders
mov ecx, esi
and ecx, 0xFFF
jz .aligned
mov eax, esi
call get_pg_addr
add eax, ecx
neg ecx
add ecx, 0x1000
mov [edi], eax
cmp ecx, [blockSize]
jnc .end
mov [edi+4], ecx
add esi, 0x1000
add edi, 8
sub [blockSize], ecx
.aligned:
mov eax, esi
call get_pg_addr
mov ecx, eax
mov [edi], eax
and ecx, 0xFFFF
neg ecx
add ecx, 0x10000
cmp [blockSize], ecx
jnc @f
mov ecx, [blockSize]
and ecx, 0xF000
jz .end
@@:
push ecx
@@:
add esi, 0x1000
add eax, 0x1000
sub ecx, 0x1000
jz @f
mov edx, eax
mov eax, esi
call get_pg_addr
cmp eax, edx
jz @b
@@:
pop edx
sub edx, ecx
mov [edi+4], edx
add edi, 8
sub [blockSize], edx
jnz .aligned
sub edi, 8
jmp @f
.end:
mov ecx, [blockSize]
mov [edi+4], ecx
@@:
mov byte [edi+7], 80h ; list end
pop esi
pop edi
; select controller Primary or Secondary
mov ecx, [IDE_controller_pointer]
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
mov eax, [hdpos]
dec eax
test eax, 10b
jz @f
add edx, 8
@@:
add edx, 2 ; Bus Master IDE Status register
mov al, 6
out dx, al ; clear Error bit and Interrupt bit
 
cmp [hd_error], 0
jne hd_read_error
add edx, 2 ; Bus Master IDE PRD Table Address
mov eax, edi
call get_pg_addr
out dx, eax ; send scatter-gather list physical address
 
pushfd
cli
mov ecx, 256
push edx
mov edx, [hdbase]
cld
rep insw
popfd
add edx, 7 ; ATACommand
mov al, bl
out dx, al ; Start hard drive
pop edx
 
pop edx eax
sub edx, 4 ; Bus Master IDE Command register
mov al, 1 ; set direction
cmp bl, 35h ; write
jz @f
add al, 8 ; read
@@:
out dx, al ; Start Bus Master
mov [IDE_common_irq_param], 14
mov eax, [hdpos]
dec eax
test eax, 10b
jz @f
inc [IDE_common_irq_param]
@@:
push edi esi ebx
xor ecx, ecx
xor esi, esi
call create_event
mov [eventPointer], eax
mov [eventID], edx
sti
mov ebx, edx
mov ecx, 300
call wait_event_timeout
test eax, eax
jnz @f
mov [IDE_common_irq_param], 0
mov eax, [eventPointer]
mov ebx, [eventID]
call destroy_event
mov [eventPointer], 0
@@:
pop ebx esi
call kernel_free
cmp [eventPointer], 0
jz .hd_error
ret
;-----------------------------------------------------------------------------
align 4
; edi -> sector, esi -> data
cache_write_pio:
; 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
jne hd_write_error
 
; ATA with 28 or 48 bit for sector number?
mov eax, [edi]
cmp eax, 0x10000000
jae .lba48
;--------------------------------------
.lba28:
pushfd
cli
xor eax, eax
mov edx, [hdbase]
inc edx
out dx, al ; ATA Features регистр "особенностей"
inc edx
inc eax
out dx, al ; ATA Sector Counter счётчик секторов
inc edx
mov eax, [edi] ; eax = sector to write
out dx, al ; LBA Low LBA (7:0)
shr eax, 8
inc edx
out dx, al ; LBA Mid LBA (15:8)
shr eax, 8
inc edx
out dx, al ; LBA High LBA (23:16)
shr eax, 8
inc edx
and al, 1+2+4+8 ; LBA (27:24)
add al, byte [hdid]
add al, 128+64+32
out dx, al ; номер головки/номер диска
inc edx
mov al, 30h ; WRITE SECTOR(S)
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)
inc eax
out dx, al ; Sector Count Current Sector count (7:0)
inc edx
mov eax, [edi]
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, [edi]
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, 34h ; WRITE SECTOR(S) EXT
out dx, al ; ATACommand регистр команд
;--------------------------------------
.continue:
.PIO:
inc edx ; ATACommand
mov al, bl
out dx, al ; Start hard drive
popfd
call wait_for_sector_buffer
 
cmp [hd_error], 0
jne hd_write_error
 
push ecx esi
 
.sectorTransfer:
call save_hd_wait_timeout
in al, dx
in al, dx
in al, dx
in al, dx
@@:
call check_hd_wait_timeout
jc .hd_error
in al, dx
test al, 8 ; ready for transfer?
jz @b
cmp [hd_setup], 1 ; do not mark error for setup request
jz @f
test al, 1 ; previous command ended up with an error
jnz .hd_error
@@:
pushfd
cli
cld
mov ecx, 256
mov edx, [hdbase]
cld
cmp bl, 34h
jz .write
rep insw
jmp @f
.write:
rep outsw
@@:
popfd
 
pop esi ecx
add edx, 7
dec dword [blockSize]
jnz .sectorTransfer
ret
;-----------------------------------------------------------------------------
align 4
save_hd_wait_timeout:
push eax
mov eax, [timer_ticks]
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
jg hd_timeout_error
 
pop eax
mov [hd_error], 0
ret
;-----------------------------------------------------------------------------
hd_timeout_error:
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_error:
cmp bl, 30h
jnc hd_write_error
;-----------------------------------------------------------------
hd_read_error:
if lang eq sp
DEBUGF 1,"K : FS - HD error de lectura\n"
560,11 → 487,9
else
DEBUGF 1,"K : FS - HD read error\n"
end if
pop edx eax
stc
ret
;-----------------------------------------------------------------------------
hd_write_error_dma:
pop esi
;-----------------------------------------------------------------
hd_write_error:
if lang eq sp
DEBUGF 1,"K : FS - HD error de escritura\n"
571,667 → 496,75
else
DEBUGF 1,"K : FS - HD write error\n"
end if
stc
ret
;-----------------------------------------------------------------------------
align 4
wait_for_hd_idle:
push eax edx
 
call save_hd_wait_timeout
 
mov edx, [hdbase]
add edx, 0x7
;--------------------------------------
align 4
wfhil1:
call check_hd_wait_timeout
 
cmp [hd_error], 0
jne @f
 
in al, dx
test al, 128
jnz wfhil1
;--------------------------------------
@@:
pop edx eax
;-----------------------------------------------------------------
save_hd_wait_timeout:
mov eax, [timer_ticks]
add eax, 300 ; 3 sec timeout
mov [hd_wait_timeout], eax
ret
;-----------------------------------------------------------------------------
align 4
wait_for_sector_buffer:
push eax edx
 
mov edx, [hdbase]
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
 
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
;--------------------------------------
;-----------------------------------------------------------------
check_hd_wait_timeout:
mov eax, [timer_ticks]
cmp [hd_wait_timeout], eax
jc @f
ret
@@:
mov [hd_error], 1
;--------------------------------------
buf_wait_ok:
pop edx eax
if lang eq sp
DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
else
DEBUGF 1,"K : FS - HD timeout\n"
end if
stc
ret
;-----------------------------------------------------------------------------
irq14_num equ byte 14
irq15_num equ byte 15
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------
align 4
wait_for_sector_dma_ide0:
push eax
push edx
call save_hd_wait_timeout
;--------------------------------------
align 4
.wait:
call change_task
 
cmp [IDE_common_irq_param], 0
jz .done
 
call check_hd_wait_timeout
 
cmp [hd_error], 0
jz .wait
 
mov [IDE_common_irq_param], 0
;--------------------------------------
.done:
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 [IDE_common_irq_param], 0
jz .done
 
call check_hd_wait_timeout
 
cmp [hd_error], 0
jz .wait
 
mov [IDE_common_irq_param], 0
;--------------------------------------
.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 IDE_DMA
dw 0x2000
dw 0x8000
 
dma_cur_sector dd not 40h
dma_hdpos dd 0
IDE_common_irq_param db 0
endg
;-----------------------------------------------------------------------------
uglobal
; all uglobals are zeroed at boot
cache_chain_ptr dd 0
cache_chain_size db 0
allow_dma_access db 0
endg
;-----------------------------------------------------------------------------
align 4
IDE_irq_14_handler:
; DEBUGF 1, 'K : IDE_irq_14_handler %x\n', [IDE_common_irq_param]:2
cmp [IDE_common_irq_param], irq14_num
jne .exit
 
pushfd
cli
pushad
mov [IDE_common_irq_param], 0
mov ecx, [IDE_controller_pointer]
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
; test whether it is our interrupt?
add edx, 2
in al, dx
test al, 100b
jz @f
; clear Bus Master IDE Status register
; clear Interrupt bit
out dx, al
; clear Bus Master IDE Command register
sub edx, 2
xor eax, eax
out dx, al
; read status register and remove the interrupt request
mov edx, [hdbase]
add edx, 0x7
in al, dx
popad
popfd
mov al, 1
ret
;--------------------------------------
@@:
popad
popfd
;--------------------------------------
.exit:
mov al, 0
ret
;-----------------------------------------------------------------------------
align 4
IDE_irq_15_handler:
; DEBUGF 1, 'K : IDE_irq_15_handler %x\n', [IDE_common_irq_param]:2
cmp [IDE_common_irq_param], irq15_num
jne .exit
 
IDE_common_irq_handler:
; DEBUGF 1, 'K : IDE_irq_handler %x\n', [IDE_common_irq_param]:2
cmp [IDE_common_irq_param], 0
jz .exit
pushfd
cli
pushad
mov [IDE_common_irq_param], 0
mov ecx, [IDE_controller_pointer]
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
add dx, 8
; test whether it is our interrupt?
add edx, 2
in al, dx
test al, 100b
cmp [IDE_common_irq_param], 14
jz @f
; clear Bus Master IDE Status register
; clear Interrupt bit
out dx, al
; clear Bus Master IDE Command register
sub edx, 2
mov al, 0
out dx, al
; read status register and remove the interrupt request
mov edx, [hdbase]
add edx, 0x7
in al, dx
popad
popfd
mov al, 1
ret
;--------------------------------------
@@:
popad
popfd
;--------------------------------------
.exit:
mov al, 0
ret
;-----------------------------------------------------------------------------
align 4
IDE_common_irq_handler:
; DEBUGF 1, 'K : IDE_common_irq_handler %x\n', [IDE_common_irq_param]:2
pushfd
cli
cmp [IDE_common_irq_param], 0
je .exit
 
pushad
xor ebx, ebx
mov ecx, [IDE_controller_pointer]
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
mov eax, IDE_common_irq_param
cmp [eax], irq14_num
mov [eax], bl
je @f
 
add dx, 8
;--------------------------------------
@@:
; test whether it is our interrupt?
add edx, 2
add edx, 2 ; Bus Master IDE Status register
in al, dx
test al, 100b
test al, 4
jz @f
; clear Bus Master IDE Status register
; clear Interrupt bit
out dx, al
; clear Bus Master IDE Command register
mov [IDE_common_irq_param], 0
out dx, al ; clear Interrupt bit
sub edx, 2
xor eax, eax
out dx, al
; read status register and remove the interrupt request
out dx, al ; clear Bus Master IDE Command register
mov edx, [hdbase]
add edx, 0x7
in al, dx
add edx, 7
in al, dx ; read status register
mov eax, [eventPointer]
mov ebx, [eventID]
xor edx, edx
xor esi, esi
call raise_event
popad
popfd
mov al, 1
mov al, 1 ; remove the interrupt request
ret
;--------------------------------------
@@:
popad
;--------------------------------------
popfd
.exit:
popfd
mov al, 0
xor eax, eax ; not our interrupt
ret
;-----------------------------------------------------------------------------
align 4
hd_read_dma:
push eax
push edx
mov edx, [dma_hdpos]
cmp edx, [hdpos]
jne .notread
 
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, (OS_BASE+IDE_DMA)
 
push ecx esi
mov esi, eax
mov ecx, 512/4
cld
rep movsd
pop esi ecx
 
pop edx
pop eax
ret
;--------------------------------------
.notread:
; set data for PRD Table
mov eax, IDE_descriptor_table
mov dword [eax], IDE_DMA
mov word [eax+4], 0x2000
sub eax, OS_BASE
; select controller Primary or Secondary
mov ecx, [IDE_controller_pointer]
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
 
push eax
mov eax, [hdpos]
dec eax
test eax, 10b
pop eax
jz @f
 
add edx, 8
;--------------------------------------
@@:
push edx
; Bus Master IDE PRD Table Address
add edx, 4
; save IDE_descriptor_table
out dx, eax
pop edx
; clear Bus Master IDE Command register
mov al, 0
out dx, al
; clear Bus Master IDE Status register
; clear Error bit and Interrupt bit
add edx, 2
mov al, 6 ; 110b
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
; 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 ; ATA Features регистр "особенностей"
inc edx
mov eax, 10h ; Sector Counter = 16 ; PreCache
out dx, al ; ATA Sector Counter счётчик секторов
inc edx
mov eax, [esp+4+4]
out dx, al ; LBA Low LBA (7:0)
shr eax, 8
inc edx
out dx, al ; LBA Mid LBA (15:8)
shr eax, 8
inc edx
out dx, al ; LBA High LBA (23:16)
shr eax, 8
inc edx
and al, 0xF ; LBA (27:24)
add al, byte [hdid]
add al, 11100000b
out dx, al ; номер головки/номер диска
inc edx
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:
; select controller Primary or Secondary
mov ecx, [IDE_controller_pointer]
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
 
mov eax, [hdpos]
dec eax
test eax, 10b
jz @f
 
add dx, 8
;--------------------------------------
@@:
; set write to memory and Start Bus Master
mov al, 9
out dx, al
 
mov eax, [hdpos]
dec eax
test eax, 10b
jnz .ide1
 
mov [IDE_common_irq_param], irq14_num
jmp @f
;--------------------------------------
.ide1:
mov [IDE_common_irq_param], irq15_num
;--------------------------------------
@@:
popfd
; wait for interrupt
mov eax, [hdpos]
dec eax
test eax, 10b
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
 
mov eax, [hdpos]
mov [dma_hdpos], eax
pop edx
pop eax
 
mov [dma_cur_sector], eax
jmp hd_read_dma
;-----------------------------------------------------------------------------
cache_write_dma:
mov eax, [cache_chain_ptr] ; for what?
push esi
; set data for PRD Table
mov eax, IDE_descriptor_table
mov edx, eax
 
pusha
mov edi, (OS_BASE+IDE_DMA)
mov dword [edx], IDE_DMA
movzx ecx, [cache_chain_size]
shl ecx, 9
mov word [edx+4], cx
shr ecx, 2
cld
rep movsd
popa
 
sub eax, OS_BASE
; select controller Primary or Secondary
mov ecx, [IDE_controller_pointer]
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
 
push eax
mov eax, [hdpos]
dec eax
test eax, 10b
pop eax
jz @f
 
add edx, 8
;--------------------------------------
@@:
push edx
; Bus Master IDE PRD Table Address
add edx, 4
; save IDE_descriptor_table
out dx, eax
pop edx
; clear Bus Master IDE Command register
mov al, 0
out dx, al
; clear Bus Master IDE Status register
; clear Error bit and Interrupt bit
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
; 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 ; ATA Features регистр "особенностей"
inc edx
mov al, [cache_chain_size] ; Sector Counter
out dx, al ; ATA Sector Counter счётчик секторов
inc edx
mov eax, [esi]
out dx, al ; LBA Low LBA (7:0)
shr eax, 8
inc edx
out dx, al ; LBA Mid LBA (15:8)
shr eax, 8
inc edx
out dx, al ; LBA High LBA (23:16)
shr eax, 8
inc edx
and al, 0xF ; LBA (27:24)
add al, byte [hdid]
add al, 11100000b
out dx, al ; номер головки/номер диска
inc edx
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:
; select controller Primary or Secondary
mov ecx, [IDE_controller_pointer]
mov dx, [ecx+IDE_DATA.RegsBaseAddres]
 
mov eax, [hdpos]
dec eax
test eax, 10b
jz @f
 
add dx, 8
;--------------------------------------
@@:
; set write to device and Start Bus Master
mov al, 1
out dx, al
 
mov eax, [hdpos]
dec eax
test eax, 10b
jnz .ide1
 
mov [IDE_common_irq_param], irq14_num
jmp @f
;--------------------------------------
.ide1:
mov [IDE_common_irq_param], irq15_num
;--------------------------------------
@@:
popfd
; wait for interrupt
mov [dma_cur_sector], not 0x40
 
mov eax, [hdpos]
dec eax
test eax, 10b
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
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------
proc clear_pci_ide_interrupts
mov esi, pcidev_list
;--------------------------------------
align 4
.loop:
mov esi, [esi+PCIDEV.fd]
1265,8 → 598,6
in al, dx
DEBUGF 1,'-> %x\n',al
jmp .loop
;--------------------------------------
.done:
ret
endp
;-----------------------------------------------------------------------------