Subversion Repositories Kolibri OS

Rev

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