Subversion Repositories Kolibri OS

Rev

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