Subversion Repositories Kolibri OS

Rev

Rev 1507 | Rev 1560 | 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: 1508 $
  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.         cmp     byte [BOOT_VAR+0x9020],2 ;what mechanism will we use?
  132.         je      pci_read_reg_2
  133.  
  134.                 ; mechanism 1
  135.         push    esi   ; save register size into ESI
  136.         mov     esi,eax
  137.         and     esi,3
  138.  
  139.         call    pci_make_config_cmd
  140.         mov     ebx,eax
  141.                 ; get current state
  142.         mov     dx,0xcf8
  143.         in      eax, dx
  144.         push    eax
  145.                 ; set up addressing to config data
  146.         mov     eax,ebx
  147.         and     al,0xfc ; make address dword-aligned
  148.         out     dx,eax
  149.                 ; get requested DWORD of config data
  150.         mov     dl,0xfc
  151.         and     bl,3
  152.         or      dl,bl    ; add to port address first 2 bits of register address
  153.  
  154.         or      esi,esi
  155.         jz      pci_read_byte1
  156.         cmp     esi,1
  157.         jz      pci_read_word1
  158.         cmp     esi,2
  159.         jz      pci_read_dword1
  160.         jmp     pci_fin_read1
  161.  
  162. pci_read_byte1:
  163.         in      al,dx
  164.         jmp pci_fin_read1
  165. pci_read_word1:
  166.         in      ax,dx
  167.         jmp pci_fin_read1
  168. pci_read_dword1:
  169.         in      eax,dx
  170.         jmp     pci_fin_read1
  171. pci_fin_read1:
  172.                 ; restore configuration control
  173.         xchg    eax,[esp]
  174.         mov     dx,0xcf8
  175.         out     dx,eax
  176.  
  177.         pop     eax
  178.         pop     esi
  179.         ret
  180. pci_read_reg_2:
  181.  
  182.         test    bh,128  ;mech#2 only supports 16 devices per bus
  183.         jnz     pci_read_reg_err
  184.  
  185.         push esi   ; save register size into ESI
  186.         mov esi,eax
  187.         and esi,3
  188.  
  189.         push    eax
  190.                 ;store current state of config space
  191.         mov     dx,0xcf8
  192.         in      al,dx
  193.         mov     ah,al
  194.         mov     dl,0xfa
  195.         in      al,dx
  196.  
  197.         xchg    eax,[esp]
  198.                 ; out 0xcfa,bus
  199.         mov     al,ah
  200.         out     dx,al
  201.                 ; out 0xcf8,0x80
  202.         mov     dl,0xf8
  203.         mov     al,0x80
  204.         out     dx,al
  205.                 ; compute addr
  206.         shr     bh,3 ; func is ignored in mechanism 2
  207.         or      bh,0xc0
  208.         mov     dx,bx
  209.  
  210.         or      esi,esi
  211.         jz      pci_read_byte2
  212.         cmp     esi,1
  213.         jz      pci_read_word2
  214.         cmp     esi,2
  215.         jz      pci_read_dword2
  216.         jmp     pci_fin_read2
  217.  
  218. pci_read_byte2:
  219.         in      al,dx
  220.         jmp pci_fin_read2
  221. pci_read_word2:
  222.         in      ax,dx
  223.         jmp pci_fin_read2
  224. pci_read_dword2:
  225.         in      eax,dx
  226. ;       jmp pci_fin_read2
  227. pci_fin_read2:
  228.  
  229.                 ; restore configuration space
  230.         xchg    eax,[esp]
  231.         mov     dx,0xcfa
  232.         out     dx,al
  233.         mov     dl,0xf8
  234.         mov     al,ah
  235.         out     dx,al
  236.  
  237.         pop     eax
  238.         pop     esi
  239.         ret
  240.  
  241. pci_read_reg_err:
  242.         xor     eax,eax
  243.         dec     eax
  244.         ret
  245.  
  246.  
  247. ;***************************************************************************
  248. ;   Function
  249. ;      pci_write_reg:
  250. ;
  251. ;   Description
  252. ;       write a register from ECX/CX/CL into the PCI config space
  253. ;       IN: ah=bus,device+func=bh,register address (dword aligned)=bl,
  254. ;           value to write in ecx
  255. ;           number of bytes to write (1,2,4) coded into AL, bits 0-1
  256. ;           (0 - byte, 1 - word, 2 - dword)
  257. ;***************************************************************************
  258.  
  259. align 4
  260.  
  261. pci_write_reg:
  262.         cmp byte [BOOT_VAR+0x9020],2 ;what mechanism will we use?
  263.         je pci_write_reg_2
  264.  
  265.                 ; mechanism 1
  266.         push    esi   ; save register size into ESI
  267.         mov     esi,eax
  268.         and     esi,3
  269.  
  270.         call    pci_make_config_cmd
  271.         mov     ebx,eax
  272.                 ; get current state into ecx
  273.         mov     dx,0xcf8
  274.         in      eax, dx
  275.         push    eax
  276.                 ; set up addressing to config data
  277.         mov     eax,ebx
  278.         and     al,0xfc ; make address dword-aligned
  279.         out     dx,eax
  280.                 ; write DWORD of config data
  281.         mov     dl,0xfc
  282.         and     bl,3
  283.         or      dl,bl
  284.         mov     eax,ecx
  285.  
  286.         or      esi,esi
  287.         jz      pci_write_byte1
  288.         cmp     esi,1
  289.         jz      pci_write_word1
  290.         cmp     esi,2
  291.         jz      pci_write_dword1
  292.         jmp     pci_fin_write1
  293.  
  294. pci_write_byte1:
  295.         out     dx,al
  296.         jmp pci_fin_write1
  297. pci_write_word1:
  298.         out     dx,ax
  299.         jmp pci_fin_write1
  300. pci_write_dword1:
  301.         out     dx,eax
  302.         jmp     pci_fin_write1
  303. pci_fin_write1:
  304.  
  305.                 ; restore configuration control
  306.         pop     eax
  307.         mov     dl,0xf8
  308.         out     dx,eax
  309.  
  310.         xor     eax,eax
  311.         pop     esi
  312.  
  313.         ret
  314. pci_write_reg_2:
  315.  
  316.         test    bh,128  ;mech#2 only supports 16 devices per bus
  317.         jnz     pci_write_reg_err
  318.  
  319.  
  320.         push esi   ; save register size into ESI
  321.         mov esi,eax
  322.         and esi,3
  323.  
  324.         push    eax
  325.                 ;store current state of config space
  326.         mov     dx,0xcf8
  327.         in      al,dx
  328.         mov     ah,al
  329.         mov     dl,0xfa
  330.         in      al,dx
  331.         xchg    eax,[esp]
  332.                 ; out 0xcfa,bus
  333.         mov     al,ah
  334.         out     dx,al
  335.                 ; out 0xcf8,0x80
  336.         mov     dl,0xf8
  337.         mov     al,0x80
  338.         out     dx,al
  339.                 ; compute addr
  340.         shr     bh,3 ; func is ignored in mechanism 2
  341.         or      bh,0xc0
  342.         mov     dx,bx
  343.                 ; write register
  344.         mov     eax,ecx
  345.  
  346.         or      esi,esi
  347.         jz      pci_write_byte2
  348.         cmp     esi,1
  349.         jz      pci_write_word2
  350.         cmp     esi,2
  351.         jz      pci_write_dword2
  352.         jmp     pci_fin_write2
  353.  
  354. pci_write_byte2:
  355.         out     dx,al
  356.         jmp pci_fin_write2
  357. pci_write_word2:
  358.         out     dx,ax
  359.         jmp pci_fin_write2
  360. pci_write_dword2:
  361.         out     dx,eax
  362.         jmp     pci_fin_write2
  363. pci_fin_write2:
  364.                 ; restore configuration space
  365.         pop     eax
  366.         mov     dx,0xcfa
  367.         out     dx,al
  368.         mov     dl,0xf8
  369.         mov     al,ah
  370.         out     dx,al
  371.  
  372.         xor     eax,eax
  373.         pop     esi
  374.         ret
  375.  
  376. pci_write_reg_err:
  377.         xor     eax,eax
  378.         dec     eax
  379.         ret
  380.  
  381. ;***************************************************************************
  382. ;   Function
  383. ;      pci_mmio_init
  384. ;
  385. ;   Description
  386. ;       IN:  bx = device's PCI bus address (bbbbbbbbdddddfff)
  387. ;   Returns  eax = phys. address of user-accessible DMA block
  388. ;   Error codes
  389. ;       eax = -1 : PCI user access blocked,
  390. ;       eax = -3 : user heap initialization failure
  391. ;***************************************************************************
  392. pci_mmio_init:
  393.     mov     [mmio_pci_addr],bx
  394.  
  395.     call    init_heap      ; (if not initialized yet)
  396.     or      eax,eax
  397.     jz      @f
  398.     mov     eax, [UserDMAaddr]
  399.     ret
  400. @@:
  401.     mov     eax,-3
  402.     ret
  403.  
  404.  
  405. ;***************************************************************************
  406. ;   Function
  407. ;      pci_mmio_map
  408. ;
  409. ;   Description
  410. ;       maps a block of PCI memory to user-accessible linear address
  411. ;
  412. ;
  413. ;       IN:  ah = BAR#; or
  414. ;       IN:  ah = 0xDA for DMA-mapping requests;
  415. ;       IN: ebx = block size (bytes);
  416. ;       IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages);
  417. ;
  418. ;   Returns eax = MMIO block's linear address in the userspace (if no error)
  419. ;
  420. ;
  421. ;   Error codes
  422. ;       eax = -1 : user access to PCI blocked,
  423. ;       eax = -2 : an invalid BAR register referred
  424. ;       eax = -3 : no i/o space on that BAR
  425. ;       eax = -4 : a port i/o BAR register referred
  426. ;       eax = -5 : dynamic userspace allocation problem
  427. ;***************************************************************************
  428.  
  429. pci_mmio_map:
  430.     and     edx,0x0ffff
  431.     cmp     ah, 0xDA
  432.     jz     .dma_map
  433.     cmp     ah,6
  434.     jc     .bar_0_5
  435.     jz     .bar_rom
  436.     mov     eax,-2
  437.     ret
  438.  
  439. .dma_map:
  440.     push    ecx
  441.     mov     ecx,ebx
  442.     mov     eax,[UserDMAaddr]
  443.     jmp    .allocate_block
  444.    
  445. .bar_rom:
  446.     mov    ah, 8        ; bar6 = Expansion ROM base address
  447. .bar_0_5:
  448.     push    ecx
  449.     add     ebx, 4095
  450.     and     ebx,-4096
  451.     push    ebx
  452.     mov     bl, ah      ; bl = BAR# (0..5), however bl=8 for BAR6
  453.     shl     bl, 1
  454.     shl     bl, 1
  455.     add     bl, 0x10    ; now bl = BAR offset in PCI config. space
  456.     mov     ax, [mmio_pci_addr]
  457.     mov     bh, al      ; bh = dddddfff
  458.     mov     al, 2       ; al : DW to read
  459.     call    pci_read_reg
  460.     or      eax, eax
  461.     jnz     @f
  462.     mov     eax,-3      ; empty I/O space
  463.     jmp     mmio_ret_fail
  464. @@:
  465.     test    eax, 1
  466.     jz      @f
  467.     mov     eax,-4      ; damned ports (not MMIO space)
  468.     jmp     mmio_ret_fail
  469. @@:
  470.     pop     ecx         ; ecx = block size, bytes (expanded to whole page)
  471.     mov     ebx, ecx    ; user_alloc destroys eax, ecx, edx, but saves ebx
  472.     and     eax, 0xFFFFFFF0
  473.  
  474. .allocate_block:
  475.     push    eax         ; store MMIO physical address + keep the stack 2x4b deep
  476.     stdcall user_alloc, ecx
  477.     or      eax, eax
  478.     jnz     mmio_map_over
  479.     mov     eax,-5      ; problem with page allocation
  480.  
  481. mmio_ret_fail:
  482.     pop     ecx
  483.     pop     edx
  484.     ret
  485.  
  486. mmio_map_over:
  487.     mov     ecx, ebx    ; ecx = size (bytes, expanded to whole page)
  488.     shr     ecx, 12     ; ecx = number of pages
  489.     mov     ebx, eax    ; ebx = linear address
  490.     pop     eax         ; eax = MMIO start
  491.     pop     edx         ; edx = MMIO shift (pages)
  492.     shl     edx, 12     ; edx = MMIO shift (bytes)
  493.     add     eax, edx    ; eax = uMMIO physical address
  494.     or      eax, (PG_SHARED+PG_UW+PG_NOCACHE)
  495.     mov     edi, ebx
  496.     call    commit_pages
  497.     mov     eax, edi
  498.     ret
  499.  
  500. ;***************************************************************************
  501. ;   Function
  502. ;      pci_mmio_unmap_page
  503. ;
  504. ;   Description
  505. ;       unmaps the linear space previously tied to a PCI memory block
  506. ;
  507. ;       IN: ebx = linear address of space previously allocated by pci_mmio_map
  508. ;       returns eax = 1 if successfully unmapped
  509. ;
  510. ;   Error codes
  511. ;       eax = -1 if no user PCI access allowed,
  512. ;       eax =  0 if unmapping failed
  513. ;***************************************************************************
  514.  
  515. pci_mmio_unmap:
  516.     stdcall user_free, ebx
  517.     ret
  518.  
  519. ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  520. uglobal
  521. align 4
  522. ; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1)
  523. pci_emu_dat:    times   30*10 db 0
  524. endg
  525. ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  526. align 4
  527. sys_pcibios:
  528.         cmp     [pci_access_enabled], 1
  529.         jne     .unsupported_func
  530.         cmp     [pci_bios_entry], 0
  531.         jz      .emulate_bios
  532.  
  533.         push    ds
  534.         mov     ax, pci_data_sel
  535.         mov     ds, ax
  536.         mov     eax, ebp
  537.         mov     ah, 0B1h
  538.         call    pword [cs:pci_bios_entry]
  539.         pop     ds
  540.  
  541.         jmp     .return
  542.         ;-=-=-=-=-=-=-=-=
  543. .emulate_bios:
  544.         cmp     ebp, 1                  ; PCI_FUNCTION_ID
  545.         jnz     .not_PCI_BIOS_PRESENT
  546.         mov     edx, 'PCI '
  547.         mov     al, [OS_BASE+0x2F0000 + 0x9020]
  548.         mov     bx, [OS_BASE+0x2F0000 + 0x9022]
  549.         mov     cl, [OS_BASE+0x2F0000 + 0x9021]
  550.         xor     ah, ah
  551.         jmp     .return_abcd
  552.  
  553. .not_PCI_BIOS_PRESENT:
  554.         cmp     ebp, 2                  ; FIND_PCI_DEVICE
  555.         jne     .not_FIND_PCI_DEVICE
  556.         mov     ebx, pci_emu_dat
  557. ..nxt:  cmp     [ebx], dx
  558.         jne     ..no
  559.         cmp     [ebx + 2], cx
  560.         jne     ..no
  561.         dec     si
  562.         jns     ..no
  563.         mov     bx, [ebx + 4]
  564.         xor     ah, ah
  565.         jmp     .return_ab
  566. ..no:   cmp     word[ebx], 0
  567.         je      ..dev_not_found
  568.         add     ebx, 10
  569.         jmp     ..nxt
  570. ..dev_not_found:
  571.         mov     ah, 0x86                ; DEVICE_NOT_FOUND
  572.         jmp     .return_a
  573.  
  574. .not_FIND_PCI_DEVICE:
  575.         cmp     ebp, 3                  ; FIND_PCI_CLASS_CODE
  576.         jne     .not_FIND_PCI_CLASS_CODE
  577.         mov     esi, pci_emu_dat
  578.         shl     ecx, 8
  579. ..nxt2: cmp     [esi], ecx
  580.         jne     ..no2
  581.         mov     bx, [esi]
  582.         xor     ah, ah
  583.         jmp     .return_ab
  584. ..no2:  cmp     dword[esi], 0
  585.         je      ..dev_not_found
  586.         add     esi, 10
  587.         jmp     ..nxt2
  588.  
  589. .not_FIND_PCI_CLASS_CODE:
  590.         cmp     ebp, 8                  ; READ_CONFIG_*
  591.         jb      .not_READ_CONFIG
  592.         cmp     ebp, 0x0A
  593.         ja      .not_READ_CONFIG
  594.         mov     eax, ebp
  595.         mov     ah, bh
  596.         mov     edx, edi
  597.         mov     bh, bl
  598.         mov     bl, dl
  599.         call    pci_read_reg
  600.         mov     ecx, eax
  601.         xor     ah, ah                  ; SUCCESSFUL
  602.         jmp     .return_abc
  603. .not_READ_CONFIG:
  604.         cmp     ebp, 0x0B               ; WRITE_CONFIG_*
  605.         jb      .not_WRITE_CONFIG
  606.         cmp     ebp, 0x0D
  607.         ja      .not_WRITE_CONFIG
  608.         lea     eax, [ebp+1]
  609.         mov     ah, bh
  610.         mov     edx, edi
  611.         mov     bh, bl
  612.         mov     bl, dl
  613.         call    pci_write_reg
  614.         xor     ah, ah                  ; SUCCESSFUL
  615.         jmp     .return_abc
  616. .not_WRITE_CONFIG:
  617. .unsupported_func:
  618.         mov     ah, 0x81                ; FUNC_NOT_SUPPORTED
  619. .return:mov     dword[esp + 4 ], edi
  620.         mov     dword[esp + 8], esi
  621. .return_abcd:
  622.         mov     dword[esp + 24], edx
  623. .return_abc:
  624.         mov     dword[esp + 28], ecx
  625. .return_ab:
  626.         mov     dword[esp + 20], ebx
  627. .return_a:
  628.         mov     dword[esp + 32], eax
  629.         ret
  630.