Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 9067 → Rev 9068

/kernel/branches/kolibri-ahci/blkdev/ahci.inc
90,6 → 90,29
vendor rd 4 ; 0x70 - 0x7F, vendor specific
ends
 
; Command header structure
struct HBA_CMD_HDR
_flags1 db ? ; 0bPWACCCCC, P - Prefetchable, W - Write (1: H2D, 0: D2H)
; A - ATAPI, C - Command FIS length in DWORDS, 2 ~ 16
_flags2 db ? ; 0bPPPPRCB(Re), P - Port multiplier port, R - Reserved,
; C - Clear busy upon R_OK, B - BIST, Re - Reset
prdtl dw ? ; Physical region descriptor table length in entries
prdbc dd ? ; Physical region descriptor byte count transferred
ctba dd ? ; Command table descriptor base address
ctbau dd ? ; Command table descriptor base address upper 32 bits
rsv1 rd 4 ; Reserved
ends
 
; Contains virtual mappings for port phys memory regions
struct PORT_DATA
clb dd ? ; Command list base
fb dd ? ; FIS base
ctba_arr rd 32 ; ctba_arr[0] = clb[0].ctba, ... and so on.
port dd ? ; address of correspoding HBA_PORT structure
ends
 
; Register FIS – Host to Device
struct FIS_REG_H2D
fis_type db ? ; FIS_TYPE_REG_H2D
215,12 → 238,13
uglobal
align 4
ahci_controller AHCI_DATA
port_data_arr rb (sizeof.PORT_DATA*AHCI_MAX_PORTS)
endg
 
; -----------------------------------------------------------------------
; detect ahci controller and initialize
align 4
init_ahci:
ahci_init:
mov ecx, ahci_controller
mov esi, pcidev_list
.find_ahci_ctr:
369,6 → 393,11
 
DEBUGF 1, "K: AHCI: found drive at port %d, signature = %x\n", ebx, [edi + HBA_PORT.signature]
 
mov ecx, ebx
shl ecx, BSF sizeof.PORT_DATA
add ecx, port_data_arr
stdcall ahci_port_rebase, edi, ebx, ecx
 
.continue_detect_drives:
inc ebx
jmp .detect_drives
381,11 → 410,9
ret
; -------------------------------------------------
 
; TODO: implement function port_rebase
 
; Start command engine
; in: eax - address of HBA_PORT structure
start_cmd:
ahci_start_cmd:
.wait_cr: ; Wait until CR (bit15) is cleared
bt [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_CR
jc .wait_cr
393,12 → 420,12
; Set FRE (bit4) and ST (bit0)
bts [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_FRE
bts [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_ST
; maybe here call ahci flush cmd ? TODO (see seakernel)
ret
 
; Stop command engine
; in: eax - address of HBA_PORT structure
stop_cmd:
ahci_stop_cmd:
btr [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_ST ; Clear ST (bit0)
btr [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_FRE ; Clear FRE (bit4)
.wait_fr_cr: ; Wait until FR (bit14), CR (bit15) are cleared
409,6 → 436,149
 
ret
 
; 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
 
; ---------------------------------------------------------------------------
; TODO: check correctness
; in: port - address of HBA_PORT structure
; portno - port index (0..31)
; pdata - address of PORT_DATA structure
proc ahci_port_rebase stdcall, port: dword, portno: dword, pdata: dword
locals
phys_page1 dd ?
virt_page1 dd ?
phys_page23 dd ?
virt_page23 dd ?
tmp dd ?
endl
 
pushad
 
DEBUGF 1, "Rebasing port %u\n", [portno]
 
mov eax, [port]
call ahci_stop_cmd
 
; Command list entry size = 32
; Command list entry maxim count = 32
; Command list maxim size = 32*32 = 1K per port
call alloc_page
mov [phys_page1], eax
 
stdcall map_io_mem, eax, 4096, PG_NOCACHE + PG_SWR ; map to virt memory so we can work with it
mov [virt_page1], eax
 
mov esi, [port]
mov ebx, [phys_page1]
mov [esi + HBA_PORT.command_list_base_l], ebx ; set the command list base
mov [esi + HBA_PORT.command_list_base_h], 0 ; zero upper 32 bits of addr cause we are 32 bit os
 
mov edi, [pdata]
mov ebx, [virt_page1]
mov [edi + PORT_DATA.clb], ebx ; set pdata->clb
 
mov eax, [port]
mov [edi + PORT_DATA.port], eax ; set pdata->port
 
stdcall _memset, ebx, 0, 1024 ; zero out the command list
; FIS entry size = 256 bytes per port
mov eax, [phys_page1]
add eax, 1024
mov [esi + HBA_PORT.fis_base_l], eax
mov [esi + HBA_PORT.fis_base_h], 0
 
mov eax, [virt_page1]
add eax, 1024
mov [edi + PORT_DATA.fb], eax ; set pdata->fb
stdcall _memset, eax, 0, 256 ; zero out
stdcall alloc_pages, 2
mov [phys_page23], eax
stdcall map_io_mem, eax, 2*4096, PG_NOCACHE + PG_SWR
mov [virt_page23], eax
 
; Command table size = 256*32 = 8K per port
mov edx, [edi + PORT_DATA.clb] ; cmdheader array base
xor ecx, ecx
 
.for1:
cmp ecx, 32
jae .for1_end
 
mov ebx, ecx
shl ebx, BSF sizeof.HBA_CMD_HDR
add ebx, edx ; ebx = cmdheader[ecx]
 
mov [ebx + HBA_CMD_HDR.prdtl], 8 ; 8 prdt entries per command table
 
; 256 bytes per command table, 64+16+48+16*8
 
push edx
; cmdheader[ecx].ctba = phys_page23 + ecx*256
mov [ebx + HBA_CMD_HDR.ctba], ecx
shl [ebx + HBA_CMD_HDR.ctba], BSF 256 ; *= 256
mov eax, [ebx + HBA_CMD_HDR.ctba]
mov edx, [phys_page23]
add [ebx + HBA_CMD_HDR.ctba], edx
 
add eax, [virt_page23]
mov [tmp], eax ; tmp = virt_page23 + ecx*256
mov eax, ecx
shl eax, BSF 4 ; *= 4
add eax, PORT_DATA.ctba_arr
add eax, edi ; eax = pdata->ctba_arr[ecx]
mov edx, [tmp]
mov [eax], edx ; pdata->ctba_arr[ecx] = virt_page23 + ecx*256
 
pop edx
 
mov [ebx + HBA_CMD_HDR.ctbau], 0
stdcall _memset, [eax], 0, 256 ; zero out
 
inc ecx
jmp .for1
.for1_end:
mov eax, [port]
call ahci_start_cmd
 
DEBUGF 1, "End rebasing port %u\n", [portno]
popad
ret
endp
 
 
 
proc _memset stdcall, dest:dword, val:byte, cnt:dword ; doesnt clobber any registers
;DEBUGF DBG_INFO, "memset(%x, %u, %u)\n", [dest], [val], [cnt]
push eax ecx edi
mov edi, dword [dest]
mov al, byte [val]
mov ecx, dword [cnt]
rep stosb
pop edi ecx eax
ret
endp
/kernel/branches/kolibri-ahci/kernel.asm
819,7 → 819,7
jmp ahci_code_end
include 'blkdev/ahci.inc'
ahci_code_end:
call init_ahci
call ahci_init
;-----------------------------------------------------------------------------
if 0
mov ax, [BOOT.sys_disk]