diff --git a/kernel/trunk/bus/pci/pci32.inc b/kernel/trunk/bus/pci/pci32.inc index e9752b2d10..a479b6125e 100644 --- a/kernel/trunk/bus/pci/pci32.inc +++ b/kernel/trunk/bus/pci/pci32.inc @@ -35,50 +35,58 @@ align 4 pci_api: - cmp [pci_access_enabled],1 - jne no_pci_access_for_applications + cmp [pci_access_enabled],1 + jne no_pci_access_for_applications - or al,al - jnz pci_fn_1 - ; PCI function 0: get pci version (AH.AL) - movzx eax,word [BOOT_VAR+0x9022] - ret + or al,al + jnz pci_fn_1 + ; PCI function 0: get pci version (AH.AL) + movzx eax,word [BOOT_VAR+0x9022] + ret pci_fn_1: - cmp al,1 - jnz pci_fn_2 + cmp al,1 + jnz pci_fn_2 - ; PCI function 1: get last bus in AL - mov al,[BOOT_VAR+0x9021] - ret + ; PCI function 1: get last bus in AL + mov al,[BOOT_VAR+0x9021] + ret pci_fn_2: - cmp al,2 - jne pci_fn_3 - ; PCI function 2: get pci access mechanism - mov al,[BOOT_VAR+0x9020] - ret + cmp al,2 + jne pci_fn_3 + ; PCI function 2: get pci access mechanism + mov al,[BOOT_VAR+0x9020] + ret pci_fn_3: - cmp al,4 - jz pci_read_reg ;byte - cmp al,5 - jz pci_read_reg ;word - cmp al,6 - jz pci_read_reg ;dword + cmp al,4 + jz pci_read_reg ;byte + cmp al,5 + jz pci_read_reg ;word + cmp al,6 + 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: - mov eax,-1 + mov eax,-1 - ret + ret ;*************************************************************************** ; Function @@ -96,10 +104,10 @@ pci_fn_3: align 4 pci_make_config_cmd: - shl eax,8 ; move bus to bits 16-23 - mov ax,bx ; combine all + shl eax,8 ; move bus to bits 16-23 + mov ax,bx ; combine all and eax,0xffffff - or eax,0x80000000 + or eax,0x80000000 ret ;*************************************************************************** @@ -116,120 +124,120 @@ pci_make_config_cmd: align 4 pci_read_reg: - cmp byte [BOOT_VAR+0x9020],2 ;what mechanism will we use? - je pci_read_reg_2 + cmp byte [BOOT_VAR+0x9020],2 ;what mechanism will we use? + je pci_read_reg_2 - ; mechanism 1 - push esi ; save register size into ESI - mov esi,eax - and esi,3 + ; mechanism 1 + push esi ; save register size into ESI + mov esi,eax + and esi,3 - call pci_make_config_cmd - mov ebx,eax - ; get current state - mov dx,0xcf8 - in eax, dx - push eax - ; set up addressing to config data - mov eax,ebx - and al,0xfc ; make address dword-aligned - out dx,eax - ; get requested DWORD of config data - mov dl,0xfc - and bl,3 - or dl,bl ; add to port address first 2 bits of register address + call pci_make_config_cmd + mov ebx,eax + ; get current state + mov dx,0xcf8 + in eax, dx + push eax + ; set up addressing to config data + mov eax,ebx + and al,0xfc ; make address dword-aligned + out dx,eax + ; get requested DWORD of config data + mov dl,0xfc + and bl,3 + or dl,bl ; add to port address first 2 bits of register address - or esi,esi - jz pci_read_byte1 - cmp esi,1 - jz pci_read_word1 - cmp esi,2 - jz pci_read_dword1 - jmp pci_fin_read1 + or esi,esi + jz pci_read_byte1 + cmp esi,1 + jz pci_read_word1 + cmp esi,2 + jz pci_read_dword1 + jmp pci_fin_read1 pci_read_byte1: - in al,dx - jmp pci_fin_read1 + in al,dx + jmp pci_fin_read1 pci_read_word1: - in ax,dx - jmp pci_fin_read1 + in ax,dx + jmp pci_fin_read1 pci_read_dword1: - in eax,dx - jmp pci_fin_read1 + in eax,dx + jmp pci_fin_read1 pci_fin_read1: - ; restore configuration control - xchg eax,[esp] - mov dx,0xcf8 - out dx,eax + ; restore configuration control + xchg eax,[esp] + mov dx,0xcf8 + out dx,eax - pop eax - pop esi - ret + pop eax + pop esi + ret pci_read_reg_2: - test bh,128 ;mech#2 only supports 16 devices per bus - jnz pci_read_reg_err + test bh,128 ;mech#2 only supports 16 devices per bus + jnz pci_read_reg_err - push esi ; save register size into ESI - mov esi,eax - and esi,3 + push esi ; save register size into ESI + mov esi,eax + and esi,3 - push eax - ;store current state of config space - mov dx,0xcf8 - in al,dx - mov ah,al - mov dl,0xfa - in al,dx + push eax + ;store current state of config space + mov dx,0xcf8 + in al,dx + mov ah,al + mov dl,0xfa + in al,dx - xchg eax,[esp] - ; out 0xcfa,bus - mov al,ah - out dx,al - ; out 0xcf8,0x80 - mov dl,0xf8 - mov al,0x80 - out dx,al - ; compute addr - shr bh,3 ; func is ignored in mechanism 2 - or bh,0xc0 - mov dx,bx + xchg eax,[esp] + ; out 0xcfa,bus + mov al,ah + out dx,al + ; out 0xcf8,0x80 + mov dl,0xf8 + mov al,0x80 + out dx,al + ; compute addr + shr bh,3 ; func is ignored in mechanism 2 + or bh,0xc0 + mov dx,bx - or esi,esi - jz pci_read_byte2 - cmp esi,1 - jz pci_read_word2 - cmp esi,2 - jz pci_read_dword2 - jmp pci_fin_read2 + or esi,esi + jz pci_read_byte2 + cmp esi,1 + jz pci_read_word2 + cmp esi,2 + jz pci_read_dword2 + jmp pci_fin_read2 pci_read_byte2: - in al,dx - jmp pci_fin_read2 + in al,dx + jmp pci_fin_read2 pci_read_word2: - in ax,dx - jmp pci_fin_read2 + in ax,dx + jmp pci_fin_read2 pci_read_dword2: - in eax,dx + in eax,dx ; jmp pci_fin_read2 pci_fin_read2: - ; restore configuration space - xchg eax,[esp] - mov dx,0xcfa - out dx,al - mov dl,0xf8 - mov al,ah - out dx,al + ; restore configuration space + xchg eax,[esp] + mov dx,0xcfa + out dx,al + mov dl,0xf8 + mov al,ah + out dx,al - pop eax - pop esi - ret + pop eax + pop esi + ret pci_read_reg_err: - xor eax,eax - dec eax - ret + xor eax,eax + dec eax + ret ;*************************************************************************** @@ -247,124 +255,257 @@ pci_read_reg_err: align 4 pci_write_reg: - cmp byte [BOOT_VAR+0x9020],2 ;what mechanism will we use? - je pci_write_reg_2 + cmp byte [BOOT_VAR+0x9020],2 ;what mechanism will we use? + je pci_write_reg_2 - ; mechanism 1 - push esi ; save register size into ESI - mov esi,eax - and esi,3 + ; mechanism 1 + push esi ; save register size into ESI + mov esi,eax + and esi,3 - call pci_make_config_cmd - mov ebx,eax - ; get current state into ecx - mov dx,0xcf8 - in eax, dx - push eax - ; set up addressing to config data - mov eax,ebx - and al,0xfc ; make address dword-aligned - out dx,eax - ; write DWORD of config data - mov dl,0xfc - and bl,3 - or dl,bl - mov eax,ecx + call pci_make_config_cmd + mov ebx,eax + ; get current state into ecx + mov dx,0xcf8 + in eax, dx + push eax + ; set up addressing to config data + mov eax,ebx + and al,0xfc ; make address dword-aligned + out dx,eax + ; write DWORD of config data + mov dl,0xfc + and bl,3 + or dl,bl + mov eax,ecx - or esi,esi - jz pci_write_byte1 - cmp esi,1 - jz pci_write_word1 - cmp esi,2 - jz pci_write_dword1 - jmp pci_fin_write1 + or esi,esi + jz pci_write_byte1 + cmp esi,1 + jz pci_write_word1 + cmp esi,2 + jz pci_write_dword1 + jmp pci_fin_write1 pci_write_byte1: - out dx,al - jmp pci_fin_write1 + out dx,al + jmp pci_fin_write1 pci_write_word1: - out dx,ax - jmp pci_fin_write1 + out dx,ax + jmp pci_fin_write1 pci_write_dword1: - out dx,eax - jmp pci_fin_write1 + out dx,eax + jmp pci_fin_write1 pci_fin_write1: - ; restore configuration control - pop eax - mov dl,0xf8 - out dx,eax + ; restore configuration control + pop eax + mov dl,0xf8 + out dx,eax - xor eax,eax - pop esi + xor eax,eax + pop esi - ret + ret pci_write_reg_2: - test bh,128 ;mech#2 only supports 16 devices per bus - jnz pci_write_reg_err + test bh,128 ;mech#2 only supports 16 devices per bus + jnz pci_write_reg_err - push esi ; save register size into ESI - mov esi,eax - and esi,3 + push esi ; save register size into ESI + mov esi,eax + and esi,3 - push eax - ;store current state of config space - mov dx,0xcf8 - in al,dx - mov ah,al - mov dl,0xfa - in al,dx - xchg eax,[esp] - ; out 0xcfa,bus - mov al,ah - out dx,al - ; out 0xcf8,0x80 - mov dl,0xf8 - mov al,0x80 - out dx,al - ; compute addr - shr bh,3 ; func is ignored in mechanism 2 - or bh,0xc0 - mov dx,bx - ; write register - mov eax,ecx + push eax + ;store current state of config space + mov dx,0xcf8 + in al,dx + mov ah,al + mov dl,0xfa + in al,dx + xchg eax,[esp] + ; out 0xcfa,bus + mov al,ah + out dx,al + ; out 0xcf8,0x80 + mov dl,0xf8 + mov al,0x80 + out dx,al + ; compute addr + shr bh,3 ; func is ignored in mechanism 2 + or bh,0xc0 + mov dx,bx + ; write register + mov eax,ecx - or esi,esi - jz pci_write_byte2 - cmp esi,1 - jz pci_write_word2 - cmp esi,2 - jz pci_write_dword2 - jmp pci_fin_write2 + or esi,esi + jz pci_write_byte2 + cmp esi,1 + jz pci_write_word2 + cmp esi,2 + jz pci_write_dword2 + jmp pci_fin_write2 pci_write_byte2: - out dx,al - jmp pci_fin_write2 + out dx,al + jmp pci_fin_write2 pci_write_word2: - out dx,ax - jmp pci_fin_write2 + out dx,ax + jmp pci_fin_write2 pci_write_dword2: - out dx,eax - jmp pci_fin_write2 + out dx,eax + jmp pci_fin_write2 pci_fin_write2: - ; restore configuration space - pop eax - mov dx,0xcfa - out dx,al - mov dl,0xf8 - mov al,ah - out dx,al + ; restore configuration space + pop eax + mov dx,0xcfa + out dx,al + mov dl,0xf8 + mov al,ah + out dx,al - xor eax,eax - pop esi - ret + xor eax,eax + pop esi + ret pci_write_reg_err: - xor eax,eax - dec eax - ret + xor eax,eax + dec eax + 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 edx, eax xchg esi, eax - xchg edi, eax + xchg edi, eax cmp [pci_access_enabled], 1 - jne .unsupported_func - cmp [pci_bios_entry], 0 + jne .unsupported_func + cmp [pci_bios_entry], 0 jz .emulate_bios - push ds - mov ax, pci_data_sel - mov ds, ax - mov eax, ebp - mov ah, 0B1h - call pword [cs:pci_bios_entry] - pop ds + push ds + mov ax, pci_data_sel + mov ds, ax + mov eax, ebp + mov ah, 0B1h + call pword [cs:pci_bios_entry] + pop ds jmp .return ;-=-=-=-=-=-=-=-= @@ -398,10 +539,10 @@ sys_pcibios: cmp ebp, 1 ; PCI_FUNCTION_ID jnz .not_PCI_BIOS_PRESENT mov edx, 'PCI ' - mov al, [OS_BASE+0x2F0000 + 0x9020] - mov bx, [OS_BASE+0x2F0000 + 0x9022] - mov cl, [OS_BASE+0x2F0000 + 0x9021] - xor ah, ah + mov al, [OS_BASE+0x2F0000 + 0x9020] + mov bx, [OS_BASE+0x2F0000 + 0x9022] + mov cl, [OS_BASE+0x2F0000 + 0x9021] + xor ah, ah jmp .return_abcd .not_PCI_BIOS_PRESENT: @@ -415,7 +556,7 @@ sys_pcibios: dec si jns ..no mov bx, [ebx + 4] - xor ah, ah + xor ah, ah jmp .return_ab ..no: cmp word[ebx], 0 je ..dev_not_found @@ -430,10 +571,10 @@ sys_pcibios: jne .not_FIND_PCI_CLASS_CODE mov esi, pci_emu_dat shl ecx, 8 -..nxt2: cmp [esi], ecx +..nxt2: cmp [esi], ecx jne ..no2 mov bx, [esi] - xor ah, ah + xor ah, ah jmp .return_ab ..no2: cmp dword[esi], 0 je ..dev_not_found @@ -445,11 +586,11 @@ sys_pcibios: jb .not_READ_CONFIG cmp ebp, 0x0A ja .not_READ_CONFIG - mov eax, ebp - mov ah, bh - mov edx, edi - mov bh, bl - mov bl, dl + mov eax, ebp + mov ah, bh + mov edx, edi + mov bh, bl + mov bl, dl call pci_read_reg mov ecx, eax xor ah, ah ; SUCCESSFUL @@ -459,11 +600,11 @@ sys_pcibios: jb .not_WRITE_CONFIG cmp ebp, 0x0D ja .not_WRITE_CONFIG - lea eax, [ebp+1] - mov ah, bh - mov edx, edi - mov bh, bl - mov bl, dl + lea eax, [ebp+1] + mov ah, bh + mov edx, edi + mov bh, bl + mov bl, dl call pci_write_reg xor ah, ah ; SUCCESSFUL jmp .return_abc