Subversion Repositories Kolibri OS

Rev

Rev 1687 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;                                                              ;;
  7. ;;  PCI32.INC                                                   ;;
  8. ;;                                                              ;;
  9. ;;  32 bit PCI driver code                                      ;;
  10. ;;                                                              ;;
  11. ;;  Version 0.4A November 4th,  2010                            ;;
  12. ;;  Version 0.4  February 2nd,  2010                            ;;
  13. ;;  Version 0.3  April 9, 2007                                  ;;
  14. ;;  Version 0.2  December 21st, 2002                            ;;
  15. ;;                                                              ;;
  16. ;;  Author: Victor Prodan, victorprodan@yahoo.com               ;;
  17. ;;          Mihailov Ilia, ghost.nsk@gmail.com                  ;;
  18. ;;          Artem Jerdev,  kolibri@jerdev.co.uk                 ;;
  19. ;;    Credits:                                                  ;;
  20. ;;          Ralf Brown                                          ;;
  21. ;;          Mike Hibbett, mikeh@oceanfree.net                   ;;
  22. ;;                                                              ;;
  23. ;;  See file COPYING for details                                ;;
  24. ;;                                                              ;;
  25. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  26.  
  27. $Revision: 1941 $
  28.  
  29. ;***************************************************************************
  30. ;   Function
  31. ;      pci_api:
  32. ;
  33. ;   Description
  34. ;       entry point for system PCI calls
  35. ;***************************************************************************
  36. align 4
  37. mmio_pci_addr   dw  0x100       ; default PCI device bdf-address
  38.         dw 0
  39.  
  40. iglobal
  41. align 4
  42. f62call:
  43.         dd      pci_fn_0
  44.         dd      pci_fn_1
  45.         dd      pci_fn_2
  46.         dd      pci_service_not_supported       ;3
  47.         dd      pci_read_reg            ;4 byte
  48.         dd      pci_read_reg            ;5 word
  49.         dd      pci_read_reg            ;6 dword
  50.         dd      pci_service_not_supported   ;7
  51.         dd      pci_write_reg           ;8 byte
  52.         dd      pci_write_reg           ;9 word
  53.         dd      pci_write_reg           ;10 dword
  54.         dd      pci_mmio_init           ;11
  55.         dd      pci_mmio_map            ;12
  56.         dd      pci_mmio_unmap          ;13
  57. endg
  58.  
  59. align 4
  60. pci_api:
  61. ;cross
  62.         mov     eax, ebx
  63.         mov     ebx, ecx
  64.         mov     ecx, edx
  65.  
  66.         cmp  [pci_access_enabled],1
  67.         jne  pci_service_not_supported
  68.  
  69.         movzx   edx, al
  70.         cmp al, 13
  71.         ja pci_service_not_supported
  72.  
  73.         call    dword [f62call+edx*4]
  74.         mov     dword [esp+32],eax
  75.  
  76.         ret
  77.  
  78. align 4
  79. pci_api_drv:
  80.  
  81.     cmp  [pci_access_enabled],1
  82.     jne  .fail
  83.  
  84.     cmp eax, 2
  85.     ja   .fail
  86.  
  87.     jmp dword [f62call+eax*4]
  88.  
  89. .fail:
  90.     or eax,-1
  91.     ret
  92.  
  93. ;; ============================================
  94.  
  95. pci_fn_0:       ; PCI function 0: get pci version (AH.AL)
  96.         movzx eax,word [BOOT_VAR+0x9022]
  97.         ret
  98.  
  99. pci_fn_1:       ; PCI function 1: get last bus in AL
  100.         mov al,[BOOT_VAR+0x9021]
  101.         ret
  102.  
  103. pci_fn_2:       ; PCI function 2: get pci access mechanism
  104.         mov al,[BOOT_VAR+0x9020]
  105.         ret
  106.  
  107. pci_service_not_supported:
  108.         or eax,-1
  109.         mov     dword [esp+32],eax
  110.         ret
  111.  
  112. ;***************************************************************************
  113. ;      (for backward compatibility only)
  114. ;      command dword returned in eax ( 10000000 bbbbbbbb dddddfff rrrrrr00 )
  115. ;***************************************************************************
  116. align 4
  117. pci_make_config_cmd:
  118.     shl     eax,8          ; move bus to bits 16-23
  119.     mov     ax,bx          ; combine all
  120.     and     eax,0xffffff
  121.     or      eax,0x80000000
  122.     ret
  123.  
  124.  
  125. ;***************************************************************************
  126. ;   Function
  127. ;      pci_read_reg:
  128. ;
  129. ;   Description
  130. ;       read a register from the PCI config space into EAX/AX/AL
  131. ;       IN: ah=bus,device+func=bh,register address=bl
  132. ;           number of bytes to read (1,2,4) coded into AL, bits 0-1
  133. ;           (0 - byte, 1 - word, 2 - dword)
  134. ;***************************************************************************
  135.  
  136. align 4
  137. pci_read_reg:
  138. ;       push    edx
  139. ;       xor     edx, edx
  140. ;       mov     dh,  ah         ; bus
  141. ;       mov     dl,  bh         ; dev+fn
  142. ;       shl     edx, 12
  143. ;       mov     dl,  bl         ; reg
  144. ;       add     edx, PCIe_CONFIG_SPACE
  145. ;
  146. ;       and     al, 2
  147. ;       jz      @f
  148. ;       mov     eax, dword[edx]
  149. ;       pop     edx
  150. ;       ret
  151. ;@@:
  152. ;       and     al, 1
  153. ;       jz      @f
  154. ;       mov     ax, word[edx]
  155. ;       pop     edx
  156. ;       ret
  157. ;@@:
  158. ;       mov     al, byte[edx]
  159. ;       pop     edx
  160. ;       ret
  161.         push    esi   ; save register size into ESI
  162.         mov     esi,eax
  163.         and     esi,3
  164.  
  165.         call    pci_make_config_cmd
  166.         mov     ebx,eax
  167.                 ; get current state
  168.         mov     dx,0xcf8
  169.         in      eax, dx
  170.         push    eax
  171.                 ; set up addressing to config data
  172.         mov     eax,ebx
  173.         and     al,0xfc ; make address dword-aligned
  174.         out     dx,eax
  175.                 ; get requested DWORD of config data
  176.         mov     dl,0xfc
  177.         and     bl,3
  178.         or      dl,bl    ; add to port address first 2 bits of register address
  179.  
  180.         or      esi,esi
  181.         jz      pci_read_byte1
  182.         cmp     esi,1
  183.         jz      pci_read_word1
  184.         cmp     esi,2
  185.         jz      pci_read_dword1
  186.         jmp     pci_fin_read1
  187.  
  188. pci_read_byte1:
  189.         in      al,dx
  190.         jmp pci_fin_read1
  191. pci_read_word1:
  192.         in      ax,dx
  193.         jmp pci_fin_read1
  194. pci_read_dword1:
  195.         in      eax,dx
  196.         jmp     pci_fin_read1
  197. pci_fin_read1:
  198.                 ; restore configuration control
  199.         xchg    eax,[esp]
  200.         mov     dx,0xcf8
  201.         out     dx,eax
  202.  
  203.         pop     eax
  204.         pop     esi
  205.         ret
  206.  
  207.  
  208.  
  209. ;***************************************************************************
  210. ;   Function
  211. ;      pci_write_reg:
  212. ;
  213. ;   Description
  214. ;       write a register from ECX/CX/CL into the PCI config space
  215. ;       IN: ah=bus,device+func=bh,register address (dword aligned)=bl,
  216. ;           value to write in ecx
  217. ;           number of bytes to write (1,2,4) coded into AL, bits 0-1
  218. ;           (0 - byte, 1 - word, 2 - dword)
  219. ;***************************************************************************
  220.  
  221. align 4
  222. pci_write_reg:
  223. ;       push    edx
  224. ;       xor     edx, edx
  225. ;       mov     dh,  ah         ; bus
  226. ;       mov     dl,  bh         ; dev+fn
  227. ;       shl     edx, 12
  228. ;       mov     dl,  bl         ; reg
  229. ;       add     edx, PCIe_CONFIG_SPACE
  230. ;
  231. ;       test    al, 2
  232. ;       jz      @f
  233. ;       mov     dword[edx], ecx
  234. ;       ret
  235. ;@@:
  236. ;       test    al, 1
  237. ;       jz      @f
  238. ;       mov     word[edx], cx
  239. ;       pop     edx
  240. ;       ret
  241. ;@@:
  242. ;       mov     byte[edx], cl
  243. ;       pop     edx
  244. ;       ret
  245.         push    esi   ; save register size into ESI
  246.         mov     esi,eax
  247.         and     esi,3
  248.  
  249.         call    pci_make_config_cmd
  250.         mov     ebx,eax
  251.                 ; get current state into ecx
  252.         mov     dx,0xcf8
  253.         in      eax, dx
  254.         push    eax
  255.                 ; set up addressing to config data
  256.         mov     eax,ebx
  257.         and     al,0xfc ; make address dword-aligned
  258.         out     dx,eax
  259.                 ; write DWORD of config data
  260.         mov     dl,0xfc
  261.         and     bl,3
  262.         or      dl,bl
  263.         mov     eax,ecx
  264.  
  265.         or      esi,esi
  266.         jz      pci_write_byte1
  267.         cmp     esi,1
  268.         jz      pci_write_word1
  269.         cmp     esi,2
  270.         jz      pci_write_dword1
  271.         jmp     pci_fin_write1
  272.  
  273. pci_write_byte1:
  274.         out     dx,al
  275.         jmp pci_fin_write1
  276. pci_write_word1:
  277.         out     dx,ax
  278.         jmp pci_fin_write1
  279. pci_write_dword1:
  280.         out     dx,eax
  281.         jmp     pci_fin_write1
  282. pci_fin_write1:
  283.  
  284.                 ; restore configuration control
  285.         pop     eax
  286.         mov     dl,0xf8
  287.         out     dx,eax
  288.         xor     eax,eax
  289.         pop     esi
  290.         ret
  291.  
  292. ;***************************************************************************
  293. ;   Function
  294. ;      pci_mmio_init
  295. ;
  296. ;   Description
  297. ;       IN:  bx = device's PCI bus address (bbbbbbbbdddddfff)
  298. ;   Returns  eax = phys. address of user-accessible DMA block
  299. ;   Error codes
  300. ;       eax = -1 : PCI user access blocked,
  301. ;       eax = -3 : user heap initialization failure
  302. ;***************************************************************************
  303. pci_mmio_init:
  304.     mov     [mmio_pci_addr],bx
  305.  
  306.     call    init_heap      ; (if not initialized yet)
  307.     or      eax,eax
  308.     jz      @f
  309.     mov     eax, [UserDMAaddr]
  310.     ret
  311. @@:
  312.     mov     eax,-3
  313.     ret
  314.  
  315.  
  316. ;***************************************************************************
  317. ;   Function
  318. ;      pci_mmio_map
  319. ;
  320. ;   Description
  321. ;       maps a block of PCI memory to user-accessible linear address
  322. ;
  323. ;
  324. ;       IN:  ah = BAR#; or
  325. ;       IN:  ah = 0xDA for DMA-mapping requests;
  326. ;       IN: ebx = block size (bytes);
  327. ;       IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages);
  328. ;
  329. ;   Returns eax = MMIO block's linear address in the userspace (if no error)
  330. ;
  331. ;
  332. ;   Error codes
  333. ;       eax = -1 : user access to PCI blocked,
  334. ;       eax = -2 : an invalid BAR register referred
  335. ;       eax = -3 : no i/o space on that BAR
  336. ;       eax = -4 : a port i/o BAR register referred
  337. ;       eax = -5 : dynamic userspace allocation problem
  338. ;***************************************************************************
  339.  
  340. pci_mmio_map:
  341.     and     edx,0x0ffff
  342.     cmp     ah, 0xDA
  343.     jz     .dma_map
  344.     cmp     ah,6
  345.     jb     .bar_0_5
  346.     jz     .bar_rom
  347.     mov     eax,-2
  348.     ret
  349.  
  350. .dma_map:
  351.     push    ecx
  352.     mov     ecx,ebx
  353.     mov     eax,[UserDMAaddr]
  354.     jmp    .allocate_block
  355.  
  356. .bar_rom:
  357.     mov    ah, 8        ; bar6 = Expansion ROM base address
  358. .bar_0_5:
  359.     push    ecx
  360.     add     ebx, 4095
  361.     and     ebx,-4096
  362.     push    ebx
  363.     mov     bl, ah      ; bl = BAR# (0..5), however bl=8 for BAR6
  364.     shl     bl, 1
  365.     shl     bl, 1
  366.     add     bl, 0x10    ; now bl = BAR offset in PCI config. space
  367.     mov     eax, dword[mmio_pci_addr]
  368.     shl     eax, 12
  369.     mov     al, bl      ; BAR offset
  370.     add     eax, PCIe_CONFIG_SPACE
  371.     mov     eax, [eax]  ; read the BAR
  372.     or      eax, eax
  373.     jnz     @f
  374.     mov     eax,-3      ; empty I/O space
  375.     jmp     mmio_ret_fail
  376. @@:
  377.     test    eax, 1
  378.     jz      @f
  379.     mov     eax,-4      ; damned ports (not MMIO space)
  380.     jmp     mmio_ret_fail
  381. @@:
  382.     pop     ecx         ; ecx = block size, bytes (expanded to whole page)
  383.     mov     ebx, ecx    ; user_alloc destroys eax, ecx, edx, but saves ebx
  384.     and     eax, 0xFFFFFFF0
  385.  
  386. .allocate_block:
  387.     push    eax         ; store MMIO physical address + keep the stack 2x4b deep
  388.     stdcall user_alloc, ecx
  389.     or      eax, eax
  390.     jnz     mmio_map_over
  391.     mov     eax,-5      ; problem with page allocation
  392.  
  393. mmio_ret_fail:
  394.     pop     ecx
  395.     pop     edx
  396.     ret
  397.  
  398. mmio_map_over:
  399.     mov     ecx, ebx    ; ecx = size (bytes, expanded to whole page)
  400.     shr     ecx, 12     ; ecx = number of pages
  401.     mov     ebx, eax    ; ebx = linear address
  402.     pop     eax         ; eax = MMIO start
  403.     pop     edx         ; edx = MMIO shift (pages)
  404.     shl     edx, 12     ; edx = MMIO shift (bytes)
  405.     add     eax, edx    ; eax = uMMIO physical address
  406.     or      eax, (PG_SHARED+PG_UW+PG_NOCACHE)
  407.     mov     edi, ebx
  408.     call    commit_pages
  409.     mov     eax, edi
  410.     ret
  411.  
  412. ;***************************************************************************
  413. ;   Function
  414. ;      pci_mmio_unmap_page
  415. ;
  416. ;   Description
  417. ;       unmaps the linear space previously tied to a PCI memory block
  418. ;
  419. ;       IN: ebx = linear address of space previously allocated by pci_mmio_map
  420. ;       returns eax = 1 if successfully unmapped
  421. ;
  422. ;   Error codes
  423. ;       eax = -1 if no user PCI access allowed,
  424. ;       eax =  0 if unmapping failed
  425. ;***************************************************************************
  426.  
  427. pci_mmio_unmap:
  428.     stdcall user_free, ebx
  429.     ret
  430.  
  431.  
  432. ;------------------------------------------------
  433. align 4
  434. sys_map1:
  435. ;       copies a block from kernel to user space
  436. ;  in: esi = address in kernel space
  437. ;      edi = eddress in user space
  438. ;      ebx = count (dwords)
  439. ; out: nothing
  440. ;------------------------------------------------
  441.         mov     ecx, ebx
  442.         pushfd
  443.         cld
  444.         rep     movsd
  445.         popfd
  446.         ret
  447.  
  448.  
  449. ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  450. uglobal
  451. align 4
  452. ; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1)
  453. pci_emu_dat:    times   30*10 db 0
  454. endg
  455. ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  456. align 4
  457. sys_pcibios:
  458.         cmp     [pci_access_enabled], 1
  459.         jne     .unsupported_func
  460.         cmp     [pci_bios_entry], 0
  461.         jz      .emulate_bios
  462.  
  463.         push    ds
  464.         mov     ax, pci_data_sel
  465.         mov     ds, ax
  466.         mov     eax, ebp
  467.         mov     ah, 0B1h
  468.         call    pword [cs:pci_bios_entry]
  469.         pop     ds
  470.  
  471.         jmp     .return
  472.         ;-=-=-=-=-=-=-=-=
  473. .emulate_bios:
  474.         cmp     ebp, 1                  ; PCI_FUNCTION_ID
  475.         jnz     .not_PCI_BIOS_PRESENT
  476.         mov     edx, 'PCI '
  477.         mov     al, [OS_BASE+0x2F0000 + 0x9020]
  478.         mov     bx, [OS_BASE+0x2F0000 + 0x9022]
  479.         mov     cl, [OS_BASE+0x2F0000 + 0x9021]
  480.         xor     ah, ah
  481.         jmp     .return_abcd
  482.  
  483. .not_PCI_BIOS_PRESENT:
  484.         cmp     ebp, 2                  ; FIND_PCI_DEVICE
  485.         jne     .not_FIND_PCI_DEVICE
  486.         mov     ebx, pci_emu_dat
  487. ..nxt:  cmp     [ebx], dx
  488.         jne     ..no
  489.         cmp     [ebx + 2], cx
  490.         jne     ..no
  491.         dec     si
  492.         jns     ..no
  493.         mov     bx, [ebx + 4]
  494.         xor     ah, ah
  495.         jmp     .return_ab
  496. ..no:   cmp     word[ebx], 0
  497.         je      ..dev_not_found
  498.         add     ebx, 10
  499.         jmp     ..nxt
  500. ..dev_not_found:
  501.         mov     ah, 0x86                ; DEVICE_NOT_FOUND
  502.         jmp     .return_a
  503.  
  504. .not_FIND_PCI_DEVICE:
  505.         cmp     ebp, 3                  ; FIND_PCI_CLASS_CODE
  506.         jne     .not_FIND_PCI_CLASS_CODE
  507.         mov     esi, pci_emu_dat
  508.         shl     ecx, 8
  509. ..nxt2: cmp     [esi], ecx
  510.         jne     ..no2
  511.         mov     bx, [esi]
  512.         xor     ah, ah
  513.         jmp     .return_ab
  514. ..no2:  cmp     dword[esi], 0
  515.         je      ..dev_not_found
  516.         add     esi, 10
  517.         jmp     ..nxt2
  518.  
  519. .not_FIND_PCI_CLASS_CODE:
  520.         cmp     ebp, 8                  ; READ_CONFIG_*
  521.         jb      .not_READ_CONFIG
  522.         cmp     ebp, 0x0A
  523.         ja      .not_READ_CONFIG
  524.         mov     eax, ebp
  525.         mov     ah, bh
  526.         mov     edx, edi
  527.         mov     bh, bl
  528.         mov     bl, dl
  529.         call    pci_read_reg
  530.         mov     ecx, eax
  531.         xor     ah, ah                  ; SUCCESSFUL
  532.         jmp     .return_abc
  533. .not_READ_CONFIG:
  534.         cmp     ebp, 0x0B               ; WRITE_CONFIG_*
  535.         jb      .not_WRITE_CONFIG
  536.         cmp     ebp, 0x0D
  537.         ja      .not_WRITE_CONFIG
  538.         lea     eax, [ebp+1]
  539.         mov     ah, bh
  540.         mov     edx, edi
  541.         mov     bh, bl
  542.         mov     bl, dl
  543.         call    pci_write_reg
  544.         xor     ah, ah                  ; SUCCESSFUL
  545.         jmp     .return_abc
  546. .not_WRITE_CONFIG:
  547. .unsupported_func:
  548.         mov     ah, 0x81                ; FUNC_NOT_SUPPORTED
  549. .return:mov     dword[esp + 4 ], edi
  550.         mov     dword[esp + 8], esi
  551. .return_abcd:
  552.         mov     dword[esp + 24], edx
  553. .return_abc:
  554.         mov     dword[esp + 28], ecx
  555. .return_ab:
  556.         mov     dword[esp + 20], ebx
  557. .return_a:
  558.         mov     dword[esp + 32], eax
  559.         ret
  560.