Subversion Repositories Kolibri OS

Rev

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