forked from KolibriOS/kolibrios
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:
parent
7bedba2c53
commit
b436ed9f25
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user