Subversion Repositories Kolibri OS

Rev

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