user MMIO functions added

git-svn-id: svn://kolibrios.org@1348 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Artem Jerdev (art_zh) 2010-01-02 14:46:26 +00:00
parent 027fb9ed41
commit 5fd05e076d

View File

@ -35,50 +35,58 @@ align 4
pci_api: pci_api:
cmp [pci_access_enabled],1 cmp [pci_access_enabled],1
jne no_pci_access_for_applications jne no_pci_access_for_applications
or al,al or al,al
jnz pci_fn_1 jnz pci_fn_1
; PCI function 0: get pci version (AH.AL) ; PCI function 0: get pci version (AH.AL)
movzx eax,word [BOOT_VAR+0x9022] movzx eax,word [BOOT_VAR+0x9022]
ret ret
pci_fn_1: pci_fn_1:
cmp al,1 cmp al,1
jnz pci_fn_2 jnz pci_fn_2
; PCI function 1: get last bus in AL ; PCI function 1: get last bus in AL
mov al,[BOOT_VAR+0x9021] mov al,[BOOT_VAR+0x9021]
ret ret
pci_fn_2: pci_fn_2:
cmp al,2 cmp al,2
jne pci_fn_3 jne pci_fn_3
; PCI function 2: get pci access mechanism ; PCI function 2: get pci access mechanism
mov al,[BOOT_VAR+0x9020] mov al,[BOOT_VAR+0x9020]
ret ret
pci_fn_3: pci_fn_3:
cmp al,4 cmp al,4
jz pci_read_reg ;byte jz pci_read_reg ;byte
cmp al,5 cmp al,5
jz pci_read_reg ;word jz pci_read_reg ;word
cmp al,6 cmp al,6
jz pci_read_reg ;dword jz pci_read_reg ;dword
cmp al,8
jz pci_write_reg ;byte
cmp al,9
jz pci_write_reg ;word
cmp al,10
jz pci_write_reg ;dword
cmp al,11 ; <<< user-level MMIO functions <<< NEW!
jz pci_mmio_init
cmp al,12
jz pci_mmio_map
cmp al,13
jz pci_mmio_unmap
cmp al,8
jz pci_write_reg ;byte
cmp al,9
jz pci_write_reg ;word
cmp al,10
jz pci_write_reg ;dword
no_pci_access_for_applications: no_pci_access_for_applications:
mov eax,-1 mov eax,-1
ret ret
;*************************************************************************** ;***************************************************************************
; Function ; Function
@ -96,10 +104,10 @@ pci_fn_3:
align 4 align 4
pci_make_config_cmd: pci_make_config_cmd:
shl eax,8 ; move bus to bits 16-23 shl eax,8 ; move bus to bits 16-23
mov ax,bx ; combine all mov ax,bx ; combine all
and eax,0xffffff and eax,0xffffff
or eax,0x80000000 or eax,0x80000000
ret ret
;*************************************************************************** ;***************************************************************************
@ -116,120 +124,120 @@ pci_make_config_cmd:
align 4 align 4
pci_read_reg: pci_read_reg:
cmp byte [BOOT_VAR+0x9020],2 ;what mechanism will we use? cmp byte [BOOT_VAR+0x9020],2 ;what mechanism will we use?
je pci_read_reg_2 je pci_read_reg_2
; mechanism 1 ; mechanism 1
push esi ; save register size into ESI push esi ; save register size into ESI
mov esi,eax mov esi,eax
and esi,3 and esi,3
call pci_make_config_cmd call pci_make_config_cmd
mov ebx,eax mov ebx,eax
; get current state ; get current state
mov dx,0xcf8 mov dx,0xcf8
in eax, dx in eax, dx
push eax push eax
; set up addressing to config data ; set up addressing to config data
mov eax,ebx mov eax,ebx
and al,0xfc ; make address dword-aligned and al,0xfc ; make address dword-aligned
out dx,eax out dx,eax
; get requested DWORD of config data ; get requested DWORD of config data
mov dl,0xfc mov dl,0xfc
and bl,3 and bl,3
or dl,bl ; add to port address first 2 bits of register address or dl,bl ; add to port address first 2 bits of register address
or esi,esi or esi,esi
jz pci_read_byte1 jz pci_read_byte1
cmp esi,1 cmp esi,1
jz pci_read_word1 jz pci_read_word1
cmp esi,2 cmp esi,2
jz pci_read_dword1 jz pci_read_dword1
jmp pci_fin_read1 jmp pci_fin_read1
pci_read_byte1: pci_read_byte1:
in al,dx in al,dx
jmp pci_fin_read1 jmp pci_fin_read1
pci_read_word1: pci_read_word1:
in ax,dx in ax,dx
jmp pci_fin_read1 jmp pci_fin_read1
pci_read_dword1: pci_read_dword1:
in eax,dx in eax,dx
jmp pci_fin_read1 jmp pci_fin_read1
pci_fin_read1: pci_fin_read1:
; restore configuration control ; restore configuration control
xchg eax,[esp] xchg eax,[esp]
mov dx,0xcf8 mov dx,0xcf8
out dx,eax out dx,eax
pop eax pop eax
pop esi pop esi
ret ret
pci_read_reg_2: pci_read_reg_2:
test bh,128 ;mech#2 only supports 16 devices per bus test bh,128 ;mech#2 only supports 16 devices per bus
jnz pci_read_reg_err jnz pci_read_reg_err
push esi ; save register size into ESI push esi ; save register size into ESI
mov esi,eax mov esi,eax
and esi,3 and esi,3
push eax push eax
;store current state of config space ;store current state of config space
mov dx,0xcf8 mov dx,0xcf8
in al,dx in al,dx
mov ah,al mov ah,al
mov dl,0xfa mov dl,0xfa
in al,dx in al,dx
xchg eax,[esp] xchg eax,[esp]
; out 0xcfa,bus ; out 0xcfa,bus
mov al,ah mov al,ah
out dx,al out dx,al
; out 0xcf8,0x80 ; out 0xcf8,0x80
mov dl,0xf8 mov dl,0xf8
mov al,0x80 mov al,0x80
out dx,al out dx,al
; compute addr ; compute addr
shr bh,3 ; func is ignored in mechanism 2 shr bh,3 ; func is ignored in mechanism 2
or bh,0xc0 or bh,0xc0
mov dx,bx mov dx,bx
or esi,esi or esi,esi
jz pci_read_byte2 jz pci_read_byte2
cmp esi,1 cmp esi,1
jz pci_read_word2 jz pci_read_word2
cmp esi,2 cmp esi,2
jz pci_read_dword2 jz pci_read_dword2
jmp pci_fin_read2 jmp pci_fin_read2
pci_read_byte2: pci_read_byte2:
in al,dx in al,dx
jmp pci_fin_read2 jmp pci_fin_read2
pci_read_word2: pci_read_word2:
in ax,dx in ax,dx
jmp pci_fin_read2 jmp pci_fin_read2
pci_read_dword2: pci_read_dword2:
in eax,dx in eax,dx
; jmp pci_fin_read2 ; jmp pci_fin_read2
pci_fin_read2: pci_fin_read2:
; restore configuration space ; restore configuration space
xchg eax,[esp] xchg eax,[esp]
mov dx,0xcfa mov dx,0xcfa
out dx,al out dx,al
mov dl,0xf8 mov dl,0xf8
mov al,ah mov al,ah
out dx,al out dx,al
pop eax pop eax
pop esi pop esi
ret ret
pci_read_reg_err: pci_read_reg_err:
xor eax,eax xor eax,eax
dec eax dec eax
ret ret
;*************************************************************************** ;***************************************************************************
@ -247,124 +255,257 @@ pci_read_reg_err:
align 4 align 4
pci_write_reg: pci_write_reg:
cmp byte [BOOT_VAR+0x9020],2 ;what mechanism will we use? cmp byte [BOOT_VAR+0x9020],2 ;what mechanism will we use?
je pci_write_reg_2 je pci_write_reg_2
; mechanism 1 ; mechanism 1
push esi ; save register size into ESI push esi ; save register size into ESI
mov esi,eax mov esi,eax
and esi,3 and esi,3
call pci_make_config_cmd call pci_make_config_cmd
mov ebx,eax mov ebx,eax
; get current state into ecx ; get current state into ecx
mov dx,0xcf8 mov dx,0xcf8
in eax, dx in eax, dx
push eax push eax
; set up addressing to config data ; set up addressing to config data
mov eax,ebx mov eax,ebx
and al,0xfc ; make address dword-aligned and al,0xfc ; make address dword-aligned
out dx,eax out dx,eax
; write DWORD of config data ; write DWORD of config data
mov dl,0xfc mov dl,0xfc
and bl,3 and bl,3
or dl,bl or dl,bl
mov eax,ecx mov eax,ecx
or esi,esi or esi,esi
jz pci_write_byte1 jz pci_write_byte1
cmp esi,1 cmp esi,1
jz pci_write_word1 jz pci_write_word1
cmp esi,2 cmp esi,2
jz pci_write_dword1 jz pci_write_dword1
jmp pci_fin_write1 jmp pci_fin_write1
pci_write_byte1: pci_write_byte1:
out dx,al out dx,al
jmp pci_fin_write1 jmp pci_fin_write1
pci_write_word1: pci_write_word1:
out dx,ax out dx,ax
jmp pci_fin_write1 jmp pci_fin_write1
pci_write_dword1: pci_write_dword1:
out dx,eax out dx,eax
jmp pci_fin_write1 jmp pci_fin_write1
pci_fin_write1: pci_fin_write1:
; restore configuration control ; restore configuration control
pop eax pop eax
mov dl,0xf8 mov dl,0xf8
out dx,eax out dx,eax
xor eax,eax xor eax,eax
pop esi pop esi
ret ret
pci_write_reg_2: pci_write_reg_2:
test bh,128 ;mech#2 only supports 16 devices per bus test bh,128 ;mech#2 only supports 16 devices per bus
jnz pci_write_reg_err jnz pci_write_reg_err
push esi ; save register size into ESI push esi ; save register size into ESI
mov esi,eax mov esi,eax
and esi,3 and esi,3
push eax push eax
;store current state of config space ;store current state of config space
mov dx,0xcf8 mov dx,0xcf8
in al,dx in al,dx
mov ah,al mov ah,al
mov dl,0xfa mov dl,0xfa
in al,dx in al,dx
xchg eax,[esp] xchg eax,[esp]
; out 0xcfa,bus ; out 0xcfa,bus
mov al,ah mov al,ah
out dx,al out dx,al
; out 0xcf8,0x80 ; out 0xcf8,0x80
mov dl,0xf8 mov dl,0xf8
mov al,0x80 mov al,0x80
out dx,al out dx,al
; compute addr ; compute addr
shr bh,3 ; func is ignored in mechanism 2 shr bh,3 ; func is ignored in mechanism 2
or bh,0xc0 or bh,0xc0
mov dx,bx mov dx,bx
; write register ; write register
mov eax,ecx mov eax,ecx
or esi,esi or esi,esi
jz pci_write_byte2 jz pci_write_byte2
cmp esi,1 cmp esi,1
jz pci_write_word2 jz pci_write_word2
cmp esi,2 cmp esi,2
jz pci_write_dword2 jz pci_write_dword2
jmp pci_fin_write2 jmp pci_fin_write2
pci_write_byte2: pci_write_byte2:
out dx,al out dx,al
jmp pci_fin_write2 jmp pci_fin_write2
pci_write_word2: pci_write_word2:
out dx,ax out dx,ax
jmp pci_fin_write2 jmp pci_fin_write2
pci_write_dword2: pci_write_dword2:
out dx,eax out dx,eax
jmp pci_fin_write2 jmp pci_fin_write2
pci_fin_write2: pci_fin_write2:
; restore configuration space ; restore configuration space
pop eax pop eax
mov dx,0xcfa mov dx,0xcfa
out dx,al out dx,al
mov dl,0xf8 mov dl,0xf8
mov al,ah mov al,ah
out dx,al out dx,al
xor eax,eax xor eax,eax
pop esi pop esi
ret ret
pci_write_reg_err: pci_write_reg_err:
xor eax,eax xor eax,eax
dec eax dec eax
ret ret
;***************************************************************************
; Function
; pci_mmio_init ; NEW!
;
; Description
; IN: bx = device's PCI bus address (bbbbbbbbdddddfff)
; returns ax = user heap space available (bytes)
; Error codes
; eax = -1 : PCI user access blocked,
; eax = -2 : device not registered for uMMIO service
; eax = -3 : user heap initialization failure
;***************************************************************************
align 4
pci_mmio_init:
cmp bx, word [mmio_pci_addr] ; must be set in kernel/data32.inc
jz @f
mov eax,-2
ret
@@:
call init_heap ; (if not initialized yet)
or eax,eax
jz @f
ret
@@:
mov eax,-3
ret
;***************************************************************************
; Function
; pci_mmio_map ; NEW!
;
; Description
; maps a block of PCI memory to user-accessible linear address
;
; WARNING! This VERY EXPERIMENTAL service is for one chosen PCI device only!
; The target device address should be set in kernel var mmio_pci_addr
;
; IN: ah = BAR#;
; IN: ebx = block size (bytes);
; IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages);
;
; Returns eax = MMIO block's linear address in the userspace (if no error)
;
;
; Error codes
; eax = -1 : user access to PCI blocked,
; eax = -2 : an invalid BAR register referred
; eax = -3 : no i/o space on that BAR
; eax = -4 : a port i/o BAR register referred
; eax = -5 : dynamic userspace allocation problem
;***************************************************************************
align 4
pci_mmio_map:
and edx,0x0ffff
cmp ah,6
jc @f
mov eax,-2
ret
@@:
push ecx
add ebx, 4095
and ebx,-4096
push ebx
mov bl, ah ; bl = BAR# (0..5)
shl bl, 1
shl bl, 1
add bl, 0x10 ; bl = BARs offset in PCI config. space
mov ax,word [mmio_pci_addr]
mov bh, al ; bh = dddddfff
mov al, 2 ; al : DW to read
call pci_read_reg
or eax, eax
jnz @f
mov eax,-3 ; empty I/O space
jmp mmio_ret_fail
@@:
test eax, 1
jz @f
mov eax,-4 ; damned ports (not MMIO space)
jmp mmio_ret_fail
@@:
pop ecx ; ecx = block size, bytes (expanded to whole page)
mov ebx, ecx ; user_alloc destroys eax, ecx, edx, but saves ebx
push eax ; store MMIO physical address + keep 2DWords in the stack
stdcall user_alloc, ecx
or eax, eax
jnz mmio_map_over
mov eax,-5 ; problem with page allocation
mmio_ret_fail:
pop ecx
pop edx
ret
mmio_map_over:
mov ecx, ebx ; ecx = size (bytes, expanded to whole page)
shr ecx, 12 ; ecx = number of pages
mov ebx, eax ; ebx = linear address
pop eax ; eax = MMIO start
pop edx ; edx = MMIO shift (pages)
shl edx, 12 ; edx = MMIO shift (bytes)
add eax, edx ; eax = uMMIO physical address
or eax, PG_SHARED
or eax, PG_UW
or eax, PG_NOCACHE
mov edi, ebx
call commit_pages
mov eax, edi
ret
;***************************************************************************
; Function
; pci_mmio_unmap_page ; NEW!
;
; Description
; unmaps the linear space previously tied to a PCI memory block
;
; IN: ebx = linear address of space previously allocated by pci_mmio_map
; returns eax = 1 if successfully unmapped
;
; Error codes
; eax = -1 if no user PCI access allowed,
; eax = 0 if unmapping failed
;***************************************************************************
align 4
pci_mmio_unmap:
stdcall user_free, ebx
ret
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
@ -378,19 +519,19 @@ sys_pcibios:
xchg ecx, eax xchg ecx, eax
xchg edx, eax xchg edx, eax
xchg esi, eax xchg esi, eax
xchg edi, eax xchg edi, eax
cmp [pci_access_enabled], 1 cmp [pci_access_enabled], 1
jne .unsupported_func jne .unsupported_func
cmp [pci_bios_entry], 0 cmp [pci_bios_entry], 0
jz .emulate_bios jz .emulate_bios
push ds push ds
mov ax, pci_data_sel mov ax, pci_data_sel
mov ds, ax mov ds, ax
mov eax, ebp mov eax, ebp
mov ah, 0B1h mov ah, 0B1h
call pword [cs:pci_bios_entry] call pword [cs:pci_bios_entry]
pop ds pop ds
jmp .return jmp .return
;-=-=-=-=-=-=-=-= ;-=-=-=-=-=-=-=-=
@ -398,10 +539,10 @@ sys_pcibios:
cmp ebp, 1 ; PCI_FUNCTION_ID cmp ebp, 1 ; PCI_FUNCTION_ID
jnz .not_PCI_BIOS_PRESENT jnz .not_PCI_BIOS_PRESENT
mov edx, 'PCI ' mov edx, 'PCI '
mov al, [OS_BASE+0x2F0000 + 0x9020] mov al, [OS_BASE+0x2F0000 + 0x9020]
mov bx, [OS_BASE+0x2F0000 + 0x9022] mov bx, [OS_BASE+0x2F0000 + 0x9022]
mov cl, [OS_BASE+0x2F0000 + 0x9021] mov cl, [OS_BASE+0x2F0000 + 0x9021]
xor ah, ah xor ah, ah
jmp .return_abcd jmp .return_abcd
.not_PCI_BIOS_PRESENT: .not_PCI_BIOS_PRESENT:
@ -415,7 +556,7 @@ sys_pcibios:
dec si dec si
jns ..no jns ..no
mov bx, [ebx + 4] mov bx, [ebx + 4]
xor ah, ah xor ah, ah
jmp .return_ab jmp .return_ab
..no: cmp word[ebx], 0 ..no: cmp word[ebx], 0
je ..dev_not_found je ..dev_not_found
@ -430,10 +571,10 @@ sys_pcibios:
jne .not_FIND_PCI_CLASS_CODE jne .not_FIND_PCI_CLASS_CODE
mov esi, pci_emu_dat mov esi, pci_emu_dat
shl ecx, 8 shl ecx, 8
..nxt2: cmp [esi], ecx ..nxt2: cmp [esi], ecx
jne ..no2 jne ..no2
mov bx, [esi] mov bx, [esi]
xor ah, ah xor ah, ah
jmp .return_ab jmp .return_ab
..no2: cmp dword[esi], 0 ..no2: cmp dword[esi], 0
je ..dev_not_found je ..dev_not_found
@ -445,11 +586,11 @@ sys_pcibios:
jb .not_READ_CONFIG jb .not_READ_CONFIG
cmp ebp, 0x0A cmp ebp, 0x0A
ja .not_READ_CONFIG ja .not_READ_CONFIG
mov eax, ebp mov eax, ebp
mov ah, bh mov ah, bh
mov edx, edi mov edx, edi
mov bh, bl mov bh, bl
mov bl, dl mov bl, dl
call pci_read_reg call pci_read_reg
mov ecx, eax mov ecx, eax
xor ah, ah ; SUCCESSFUL xor ah, ah ; SUCCESSFUL
@ -459,11 +600,11 @@ sys_pcibios:
jb .not_WRITE_CONFIG jb .not_WRITE_CONFIG
cmp ebp, 0x0D cmp ebp, 0x0D
ja .not_WRITE_CONFIG ja .not_WRITE_CONFIG
lea eax, [ebp+1] lea eax, [ebp+1]
mov ah, bh mov ah, bh
mov edx, edi mov edx, edi
mov bh, bl mov bh, bl
mov bl, dl mov bl, dl
call pci_write_reg call pci_write_reg
xor ah, ah ; SUCCESSFUL xor ah, ah ; SUCCESSFUL
jmp .return_abc jmp .return_abc