Subversion Repositories Kolibri OS

Rev

Rev 1599 | Go to most recent revision | 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: 1687 $
  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. uglobal
  433. align 4
  434. ; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1)
  435. pci_emu_dat:    times   30*10 db 0
  436. endg
  437. ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  438. align 4
  439. sys_pcibios:
  440.         cmp     [pci_access_enabled], 1
  441.         jne     .unsupported_func
  442.         cmp     [pci_bios_entry], 0
  443.         jz      .emulate_bios
  444.  
  445.         push    ds
  446.         mov     ax, pci_data_sel
  447.         mov     ds, ax
  448.         mov     eax, ebp
  449.         mov     ah, 0B1h
  450.         call    pword [cs:pci_bios_entry]
  451.         pop     ds
  452.  
  453.         jmp     .return
  454.         ;-=-=-=-=-=-=-=-=
  455. .emulate_bios:
  456.         cmp     ebp, 1                  ; PCI_FUNCTION_ID
  457.         jnz     .not_PCI_BIOS_PRESENT
  458.         mov     edx, 'PCI '
  459.         mov     al, [OS_BASE+0x2F0000 + 0x9020]
  460.         mov     bx, [OS_BASE+0x2F0000 + 0x9022]
  461.         mov     cl, [OS_BASE+0x2F0000 + 0x9021]
  462.         xor     ah, ah
  463.         jmp     .return_abcd
  464.  
  465. .not_PCI_BIOS_PRESENT:
  466.         cmp     ebp, 2                  ; FIND_PCI_DEVICE
  467.         jne     .not_FIND_PCI_DEVICE
  468.         mov     ebx, pci_emu_dat
  469. ..nxt:  cmp     [ebx], dx
  470.         jne     ..no
  471.         cmp     [ebx + 2], cx
  472.         jne     ..no
  473.         dec     si
  474.         jns     ..no
  475.         mov     bx, [ebx + 4]
  476.         xor     ah, ah
  477.         jmp     .return_ab
  478. ..no:   cmp     word[ebx], 0
  479.         je      ..dev_not_found
  480.         add     ebx, 10
  481.         jmp     ..nxt
  482. ..dev_not_found:
  483.         mov     ah, 0x86                ; DEVICE_NOT_FOUND
  484.         jmp     .return_a
  485.  
  486. .not_FIND_PCI_DEVICE:
  487.         cmp     ebp, 3                  ; FIND_PCI_CLASS_CODE
  488.         jne     .not_FIND_PCI_CLASS_CODE
  489.         mov     esi, pci_emu_dat
  490.         shl     ecx, 8
  491. ..nxt2: cmp     [esi], ecx
  492.         jne     ..no2
  493.         mov     bx, [esi]
  494.         xor     ah, ah
  495.         jmp     .return_ab
  496. ..no2:  cmp     dword[esi], 0
  497.         je      ..dev_not_found
  498.         add     esi, 10
  499.         jmp     ..nxt2
  500.  
  501. .not_FIND_PCI_CLASS_CODE:
  502.         cmp     ebp, 8                  ; READ_CONFIG_*
  503.         jb      .not_READ_CONFIG
  504.         cmp     ebp, 0x0A
  505.         ja      .not_READ_CONFIG
  506.         mov     eax, ebp
  507.         mov     ah, bh
  508.         mov     edx, edi
  509.         mov     bh, bl
  510.         mov     bl, dl
  511.         call    pci_read_reg
  512.         mov     ecx, eax
  513.         xor     ah, ah                  ; SUCCESSFUL
  514.         jmp     .return_abc
  515. .not_READ_CONFIG:
  516.         cmp     ebp, 0x0B               ; WRITE_CONFIG_*
  517.         jb      .not_WRITE_CONFIG
  518.         cmp     ebp, 0x0D
  519.         ja      .not_WRITE_CONFIG
  520.         lea     eax, [ebp+1]
  521.         mov     ah, bh
  522.         mov     edx, edi
  523.         mov     bh, bl
  524.         mov     bl, dl
  525.         call    pci_write_reg
  526.         xor     ah, ah                  ; SUCCESSFUL
  527.         jmp     .return_abc
  528. .not_WRITE_CONFIG:
  529. .unsupported_func:
  530.         mov     ah, 0x81                ; FUNC_NOT_SUPPORTED
  531. .return:mov     dword[esp + 4 ], edi
  532.         mov     dword[esp + 8], esi
  533. .return_abcd:
  534.         mov     dword[esp + 24], edx
  535. .return_abc:
  536.         mov     dword[esp + 28], ecx
  537. .return_ab:
  538.         mov     dword[esp + 20], ebx
  539. .return_a:
  540.         mov     dword[esp + 32], eax
  541.         ret
  542.