Subversion Repositories Kolibri OS

Rev

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