Subversion Repositories Kolibri OS

Rev

Rev 1505 | Rev 1508 | 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: 1507 $
  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. if defined mmio_pci_addr        ; must be set above
  382. ;***************************************************************************
  383. ;   Function
  384. ;      pci_mmio_init
  385. ;
  386. ;   Description
  387. ;       IN:  bx = device's PCI bus address (bbbbbbbbdddddfff)
  388. ;   Returns  eax = phys. address of user-accessible DMA block
  389. ;   Error codes
  390. ;       eax = -1 : PCI user access blocked,
  391. ;       eax = -2 : device not registered for uMMIO service
  392. ;       eax = -3 : user heap initialization failure
  393. ;***************************************************************************
  394. pci_mmio_init:
  395.     cmp     bx, [mmio_pci_addr]
  396.     jz      @f
  397.     mov     eax,-2
  398.     ret
  399. @@:
  400.     call    init_heap      ; (if not initialized yet)
  401.     or      eax,eax
  402.     jz      @f
  403.     mov     eax, [UserDMAaddr]
  404.     ret
  405. @@:
  406.     mov     eax,-3
  407.     ret
  408.  
  409.  
  410. ;***************************************************************************
  411. ;   Function
  412. ;      pci_mmio_map
  413. ;
  414. ;   Description
  415. ;       maps a block of PCI memory to user-accessible linear address
  416. ;
  417. ;
  418. ;       IN:  ah = BAR#; or
  419. ;       IN:  ah = 0xDA for DMA-mapping requests;
  420. ;       IN: ebx = block size (bytes);
  421. ;       IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages);
  422. ;
  423. ;   Returns eax = MMIO block's linear address in the userspace (if no error)
  424. ;
  425. ;
  426. ;   Error codes
  427. ;       eax = -1 : user access to PCI blocked,
  428. ;       eax = -2 : an invalid BAR register referred
  429. ;       eax = -3 : no i/o space on that BAR
  430. ;       eax = -4 : a port i/o BAR register referred
  431. ;       eax = -5 : dynamic userspace allocation problem
  432. ;***************************************************************************
  433.  
  434. pci_mmio_map:
  435.     and     edx,0x0ffff
  436.     cmp     ah, 0xDA
  437.     jz     .dma_map
  438.     cmp     ah,6
  439.     jc     .bar_0_5
  440.     jz     .bar_rom
  441.     mov     eax,-2
  442.     ret
  443.  
  444. .dma_map:
  445.     push    ecx
  446.     mov     ecx,ebx
  447.     mov     eax,[UserDMAaddr]
  448.     jmp    .allocate_block
  449.    
  450. .bar_rom:
  451.     mov    ah, 8        ; bar6 = Expansion ROM base address
  452. .bar_0_5:
  453.     push    ecx
  454.     add     ebx, 4095
  455.     and     ebx,-4096
  456.     push    ebx
  457.     mov     bl, ah      ; bl = BAR# (0..5), however bl=8 for BAR6
  458.     shl     bl, 1
  459.     shl     bl, 1
  460.     add     bl, 0x10    ; now bl = BAR offset in PCI config. space
  461.     mov     ax, [mmio_pci_addr]
  462.     mov     bh, al      ; bh = dddddfff
  463.     mov     al, 2       ; al : DW to read
  464.     call    pci_read_reg
  465.     or      eax, eax
  466.     jnz     @f
  467.     mov     eax,-3      ; empty I/O space
  468.     jmp     mmio_ret_fail
  469. @@:
  470.     test    eax, 1
  471.     jz      @f
  472.     mov     eax,-4      ; damned ports (not MMIO space)
  473.     jmp     mmio_ret_fail
  474. @@:
  475.     pop     ecx         ; ecx = block size, bytes (expanded to whole page)
  476.     mov     ebx, ecx    ; user_alloc destroys eax, ecx, edx, but saves ebx
  477.     and     eax, 0xFFFFFFF0
  478.  
  479. .allocate_block:
  480.     push    eax         ; store MMIO physical address + keep the stack 2x4b deep
  481.     stdcall user_alloc, ecx
  482.     or      eax, eax
  483.     jnz     mmio_map_over
  484.     mov     eax,-5      ; problem with page allocation
  485.  
  486. mmio_ret_fail:
  487.     pop     ecx
  488.     pop     edx
  489.     ret
  490.  
  491. mmio_map_over:
  492.     mov     ecx, ebx    ; ecx = size (bytes, expanded to whole page)
  493.     shr     ecx, 12     ; ecx = number of pages
  494.     mov     ebx, eax    ; ebx = linear address
  495.     pop     eax         ; eax = MMIO start
  496.     pop     edx         ; edx = MMIO shift (pages)
  497.     shl     edx, 12     ; edx = MMIO shift (bytes)
  498.     add     eax, edx    ; eax = uMMIO physical address
  499.     or      eax, (PG_SHARED+PG_UW+PG_NOCACHE)
  500.     mov     edi, ebx
  501.     call    commit_pages
  502.     mov     eax, edi
  503.     ret
  504.  
  505. ;***************************************************************************
  506. ;   Function
  507. ;      pci_mmio_unmap_page
  508. ;
  509. ;   Description
  510. ;       unmaps the linear space previously tied to a PCI memory block
  511. ;
  512. ;       IN: ebx = linear address of space previously allocated by pci_mmio_map
  513. ;       returns eax = 1 if successfully unmapped
  514. ;
  515. ;   Error codes
  516. ;       eax = -1 if no user PCI access allowed,
  517. ;       eax =  0 if unmapping failed
  518. ;***************************************************************************
  519.  
  520. pci_mmio_unmap:
  521.     stdcall user_free, ebx
  522.     ret
  523.  
  524. end if
  525.  
  526. ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  527. uglobal
  528. align 4
  529. ; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1)
  530. pci_emu_dat:    times   30*10 db 0
  531. endg
  532. ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  533. align 4
  534. sys_pcibios:
  535.         cmp     [pci_access_enabled], 1
  536.         jne     .unsupported_func
  537.         cmp     [pci_bios_entry], 0
  538.         jz      .emulate_bios
  539.  
  540.         push    ds
  541.         mov     ax, pci_data_sel
  542.         mov     ds, ax
  543.         mov     eax, ebp
  544.         mov     ah, 0B1h
  545.         call    pword [cs:pci_bios_entry]
  546.         pop     ds
  547.  
  548.         jmp     .return
  549.         ;-=-=-=-=-=-=-=-=
  550. .emulate_bios:
  551.         cmp     ebp, 1                  ; PCI_FUNCTION_ID
  552.         jnz     .not_PCI_BIOS_PRESENT
  553.         mov     edx, 'PCI '
  554.         mov     al, [OS_BASE+0x2F0000 + 0x9020]
  555.         mov     bx, [OS_BASE+0x2F0000 + 0x9022]
  556.         mov     cl, [OS_BASE+0x2F0000 + 0x9021]
  557.         xor     ah, ah
  558.         jmp     .return_abcd
  559.  
  560. .not_PCI_BIOS_PRESENT:
  561.         cmp     ebp, 2                  ; FIND_PCI_DEVICE
  562.         jne     .not_FIND_PCI_DEVICE
  563.         mov     ebx, pci_emu_dat
  564. ..nxt:  cmp     [ebx], dx
  565.         jne     ..no
  566.         cmp     [ebx + 2], cx
  567.         jne     ..no
  568.         dec     si
  569.         jns     ..no
  570.         mov     bx, [ebx + 4]
  571.         xor     ah, ah
  572.         jmp     .return_ab
  573. ..no:   cmp     word[ebx], 0
  574.         je      ..dev_not_found
  575.         add     ebx, 10
  576.         jmp     ..nxt
  577. ..dev_not_found:
  578.         mov     ah, 0x86                ; DEVICE_NOT_FOUND
  579.         jmp     .return_a
  580.  
  581. .not_FIND_PCI_DEVICE:
  582.         cmp     ebp, 3                  ; FIND_PCI_CLASS_CODE
  583.         jne     .not_FIND_PCI_CLASS_CODE
  584.         mov     esi, pci_emu_dat
  585.         shl     ecx, 8
  586. ..nxt2: cmp     [esi], ecx
  587.         jne     ..no2
  588.         mov     bx, [esi]
  589.         xor     ah, ah
  590.         jmp     .return_ab
  591. ..no2:  cmp     dword[esi], 0
  592.         je      ..dev_not_found
  593.         add     esi, 10
  594.         jmp     ..nxt2
  595.  
  596. .not_FIND_PCI_CLASS_CODE:
  597.         cmp     ebp, 8                  ; READ_CONFIG_*
  598.         jb      .not_READ_CONFIG
  599.         cmp     ebp, 0x0A
  600.         ja      .not_READ_CONFIG
  601.         mov     eax, ebp
  602.         mov     ah, bh
  603.         mov     edx, edi
  604.         mov     bh, bl
  605.         mov     bl, dl
  606.         call    pci_read_reg
  607.         mov     ecx, eax
  608.         xor     ah, ah                  ; SUCCESSFUL
  609.         jmp     .return_abc
  610. .not_READ_CONFIG:
  611.         cmp     ebp, 0x0B               ; WRITE_CONFIG_*
  612.         jb      .not_WRITE_CONFIG
  613.         cmp     ebp, 0x0D
  614.         ja      .not_WRITE_CONFIG
  615.         lea     eax, [ebp+1]
  616.         mov     ah, bh
  617.         mov     edx, edi
  618.         mov     bh, bl
  619.         mov     bl, dl
  620.         call    pci_write_reg
  621.         xor     ah, ah                  ; SUCCESSFUL
  622.         jmp     .return_abc
  623. .not_WRITE_CONFIG:
  624. .unsupported_func:
  625.         mov     ah, 0x81                ; FUNC_NOT_SUPPORTED
  626. .return:mov     dword[esp + 4 ], edi
  627.         mov     dword[esp + 8], esi
  628. .return_abcd:
  629.         mov     dword[esp + 24], edx
  630. .return_abc:
  631.         mov     dword[esp + 28], ecx
  632. .return_ab:
  633.         mov     dword[esp + 20], ebx
  634. .return_a:
  635.         mov     dword[esp + 32], eax
  636.         ret
  637.