kolibri-ahci:

- use spinlocks (added two functions) instead of delays in ahci_port_identify
- small changes

git-svn-id: svn://kolibrios.org@9139 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Rustem Gimadutdinov (rgimad) 2021-08-18 11:09:40 +00:00
parent 7bedba2c53
commit b436ed9f25

View File

@ -26,6 +26,10 @@ AHCI_DEV_SATAPI = 4
; ATA commands ; ATA commands
ATA_IDENTIFY = 0xEC ATA_IDENTIFY = 0xEC
; ATA constants
ATA_DEV_BUSY = 0x80
ATA_DEV_DRQ = 0x08
; ATAPI commands ; ATAPI commands
ATAPI_IDENTIFY = 0xA1 ATAPI_IDENTIFY = 0xA1
@ -45,6 +49,7 @@ bit_AHCI_HBA_PxCMD_ST = 0
bit_AHCI_HBA_PxCMD_FRE = 4 bit_AHCI_HBA_PxCMD_FRE = 4
bit_AHCI_HBA_PxCMD_FR = 14 bit_AHCI_HBA_PxCMD_FR = 14
bit_AHCI_HBA_PxCMD_CR = 15 bit_AHCI_HBA_PxCMD_CR = 15
bit_AHCI_HBA_PxIS_TFES = 30
AHCI_HBA_PxCMD_ST = 1 shl 0 AHCI_HBA_PxCMD_ST = 1 shl 0
AHCI_HBA_PxCMD_FRE = 1 shl 4 AHCI_HBA_PxCMD_FRE = 1 shl 4
@ -60,6 +65,8 @@ AHCI_HBA_PxSSTS_DET_PRESENT = 3
AHCI_MAX_PORTS = 32 ; AHCI_MAX_PORTS = 32 ;
;HBA_MEMORY_SIZE = 0x1100 ;HBA_MEMORY_SIZE = 0x1100
AHCI_PORT_TIMEOUT = 1000000
; Frame Information Structure Types ; Frame Information Structure Types
FIS_TYPE_REG_H2D = 0x27 ; Register FIS - host to device FIS_TYPE_REG_H2D = 0x27 ; Register FIS - host to device
FIS_TYPE_REG_D2H = 0x34 ; Register FIS - device to host FIS_TYPE_REG_D2H = 0x34 ; Register FIS - device to host
@ -619,37 +626,21 @@ proc ahci_port_identify stdcall, pdata: dword
@@: @@:
mov byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.device], 0 mov byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.device], 0
; TODO Wait on previous command to complete. AHCIPortWait(bd->port_num, tS + 2); ; Wait on previous command to complete, before issuing new command.
mov ebx, 20 ;;; stdcall ahci_port_wait, edi, AHCI_PORT_TIMEOUT
call delay_hs ;;; ; DEBUGF 1, "eax = %x\n", eax
; TODO check eax error value
mov eax, [cmdslot] mov eax, [cmdslot]
bts [edi + HBA_PORT.command_issue], eax ; Issue the command bts [edi + HBA_PORT.command_issue], eax ; Issue the command
; TODO AHCIPortCmdWait(bd->port_num, cmd_slot); ; Wait for command completion
mov ebx, 20 ;;; stdcall ahci_port_cmd_wait, edi, eax;, AHCI_PORT_CMD_TIMEOUT
call delay_hs ;;; ; DEBUGF 1, " eax = %x\n", eax
; TODO check eax error value
; DEBUGF 1, "sata_error register = 0x%x\n", [edi + HBA_PORT.sata_error] ; DEBUGF 1, "sata_error register = 0x%x\n", [edi + HBA_PORT.sata_error]
; mov ecx, ecx
; mov esi, [buf_virt]
; .print_ident:
; cmp ecx, 512 - 1 ; why -1 ?
; jae .end_print_ident
; mov al, byte [esi + ecx]
; mov byte [modelstr], al
; mov byte [modelstr + 1], 0
; DEBUGF 1, "(%s) ", modelstr
; inc ecx
; jmp .print_ident
; .end_print_ident:
; DEBUGF 1, "\n"
; DEBUGF 1, "after identification: signature = 0x%x\n", [edi + HBA_PORT.signature]
mov esi, [buf_virt] mov esi, [buf_virt]
add esi, 27*2 add esi, 27*2
mov edi, modelstr mov edi, modelstr
@ -702,28 +693,84 @@ ahci_stop_cmd:
ret ret
; The commands may not take effect until the command ; waits until the port is no longer busy before issuing a new command
; register is read again by software, because reasons. ; in: [port] - address of HBA_PORT structure
; in: eax - address of HBA_PORT structure ; [timeout] - timeout (in iterations)
; out: eax - command register value ; out: eax = 0 if success, 1 if timeout expired
ahci_flush_cmd: proc ahci_port_wait stdcall, port: dword, timeout: dword
mov eax, [eax + HBA_PORT.command] push ebx ecx
mov ebx, [port]
xor ecx, ecx
.wait:
cmp ecx, [timeout]
jae .wait_end
mov eax, [ebx + HBA_PORT.task_file_data]
and eax, ATA_DEV_BUSY or ATA_DEV_DRQ
test eax, eax
jz .wait_end
inc ecx
jmp .wait
.wait_end:
xor eax, eax
DEBUGF 1, "port wait counter = %u\n", ecx
cmp ecx, [timeout] ; if they equal it means port is hung
setz al
pop ecx ebx
ret ret
endp
; Send command to port
; in: eax - address of HBA_PORT structure
; ebx - index of command slot
ahci_send_cmd:
push ecx
mov [eax + HBA_PORT.interrupt_status], 0xFFFFFFFF
mov cl, bl ; Wait for command completion
mov [eax + HBA_PORT.command_issue], 1 ; in: [port] - address of HBA_PORT structure
shl [eax + HBA_PORT.command_issue], cl ; [cmdslot] - number of command slot
; out: eax = 0 if success, 1 if error
call ahci_flush_cmd proc ahci_port_cmd_wait stdcall, port: dword, cmdslot: dword ;, timeout: dword
pop ecx push ebx ecx edx
mov ebx, [port]
mov edx, [cmdslot]
xor eax, eax
xor ecx, ecx
.wait:
bt [ebx + HBA_PORT.command_issue], edx
jnc .wait_end
bt [ebx + HBA_PORT.interrupt_status], bit_AHCI_HBA_PxIS_TFES ; check for Task File Error
jc .error
inc ecx
jmp .wait
.wait_end:
DEBUGF 1, "port cmd wait counter = %u\n", ecx
bt [ebx + HBA_PORT.interrupt_status], bit_AHCI_HBA_PxIS_TFES ; check for Task File Error
jc .error
jmp .ret
.error:
mov eax, 1
.ret:
pop edx ecx ebx
ret ret
endp
; ; The commands may not take effect until the command
; ; register is read again by software, because reasons.
; ; in: eax - address of HBA_PORT structure
; ; out: eax - command register value
; ahci_flush_cmd:
; mov eax, [eax + HBA_PORT.command]
; ret
; ; Send command to port
; ; in: eax - address of HBA_PORT structure
; ; ebx - index of command slot
; ahci_send_cmd:
; push ecx
; mov [eax + HBA_PORT.interrupt_status], 0xFFFFFFFF
; mov cl, bl
; mov [eax + HBA_PORT.command_issue], 1
; shl [eax + HBA_PORT.command_issue], cl
; call ahci_flush_cmd
; pop ecx
; ret
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; in: port - address of HBA_PORT structure ; in: port - address of HBA_PORT structure