Subversion Repositories Kolibri OS

Rev

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